From 2521c930d2eed650e0ba87b691621405430e811b Mon Sep 17 00:00:00 2001
From: Silas Davis <silas@monax.io>
Date: Mon, 8 Jan 2018 13:16:06 +0000
Subject: [PATCH] Execution/EVM Execution: remove manager package/notion to
 simplify and improve structure (we only have one manager), remove pipe
 (busywork and not really a pipe), use account, blockchain, and state types
 and interfaces throughout. TxCache, BlockCache, and State. Encapsulate Tx
 execution in Executor interfaces. Implement Tendermint 0.12 ABCI app.
 Refactor tests to support new interfaces and make minor improvements to them.

EVM: Use single definitions of state from account packages and use immutable
Account instead of separate vm accounts. Emit vm debug in standard
logging. Reorganise package. Use strongly typed Address.

Signed-off-by: Silas Davis <silas@monax.io>
---
 definitions/pipe.go                           |   85 --
 definitions/tendermint_pipe.go                |   77 -
 execution/accounts.go                         |  246 +++
 execution/block_cache.go                      |  386 +++++
 execution/events/events.go                    |   51 +
 .../evm/abi/types.go                          |    0
 execution/evm/accounts.go                     |   25 +
 execution/evm/asm/bc/helpers.go               |   68 +
 .../opcodes => execution/evm/asm}/opcodes.go  |   58 +-
 .../burrow-mint => execution}/evm/common.go   |    2 +-
 execution/evm/events/events.go                |   54 +
 execution/evm/fake_app_state.go               |   87 ++
 {manager/burrow-mint => execution}/evm/gas.go |   26 +-
 .../evm/log_event_test.go                     |   48 +-
 .../burrow-mint => execution}/evm/memory.go   |   12 +-
 .../evm/memory_test.go                        |    2 +-
 .../burrow-mint => execution}/evm/native.go   |   27 +-
 execution/evm/sha3/LICENSE                    |   27 +
 execution/evm/sha3/PATENTS                    |   22 +
 .../evm/sha3/keccakf.go                       |    0
 .../evm/sha3/sha3.go                          |    0
 .../burrow-mint => execution}/evm/snative.go  |  274 ++--
 .../evm/snative_test.go                       |   55 +-
 .../burrow-mint => execution}/evm/stack.go    |   30 +-
 {manager/burrow-mint => execution}/evm/vm.go  |  407 ++---
 .../burrow-mint => execution}/evm/vm_test.go  |  254 ++--
 .../state => execution}/execution.go          | 1130 +++++++-------
 execution/execution_test.go                   | 1329 +++++++++++++++++
 {manager/burrow-mint => execution}/namereg.go |  100 +-
 .../burrow-mint/state => execution}/state.go  |  543 ++++---
 .../state => execution}/state_test.go         |  623 ++++----
 execution/transactor.go                       |  457 ++++++
 execution/tx_cache.go                         |  128 ++
 manager/burrow-mint/accounts.go               |  228 ---
 manager/burrow-mint/burrow-mint.go            |  216 ---
 manager/burrow-mint/evm/fake_app_state.go     |   94 --
 manager/burrow-mint/evm/types.go              |   65 -
 manager/burrow-mint/pipe.go                   |  677 ---------
 manager/burrow-mint/state/block_cache.go      |  304 ----
 manager/burrow-mint/state/common.go           |   32 -
 manager/burrow-mint/state/genesis_test.go     |  172 ---
 manager/burrow-mint/state/permissions_test.go | 1314 ----------------
 manager/burrow-mint/state/tx_cache.go         |  218 ---
 manager/burrow-mint/state/tx_cache_test.go    |   36 -
 manager/burrow-mint/transactor.go             |  438 ------
 manager/burrow-mint/version.go                |   53 -
 manager/manager.go                            |   44 -
 manager/types/application.go                  |  104 --
 rpc/v0/rest_server_pipe_test.go               |  313 ----
 util/snatives/cmd/main.go                     |    4 +-
 util/snatives/templates/solidity_templates.go |   12 +-
 .../templates/solidity_templates_test.go      |    6 +-
 52 files changed, 4820 insertions(+), 6143 deletions(-)
 delete mode 100644 definitions/pipe.go
 delete mode 100644 definitions/tendermint_pipe.go
 create mode 100644 execution/accounts.go
 create mode 100644 execution/block_cache.go
 create mode 100644 execution/events/events.go
 rename {manager/burrow-mint => execution}/evm/abi/types.go (100%)
 create mode 100644 execution/evm/accounts.go
 create mode 100644 execution/evm/asm/bc/helpers.go
 rename {manager/burrow-mint/evm/opcodes => execution/evm/asm}/opcodes.go (81%)
 rename {manager/burrow-mint => execution}/evm/common.go (98%)
 create mode 100644 execution/evm/events/events.go
 create mode 100644 execution/evm/fake_app_state.go
 rename {manager/burrow-mint => execution}/evm/gas.go (62%)
 rename {manager/burrow-mint => execution}/evm/log_event_test.go (65%)
 rename {manager/burrow-mint => execution}/evm/memory.go (91%)
 rename {manager/burrow-mint => execution}/evm/memory_test.go (99%)
 rename {manager/burrow-mint => execution}/evm/native.go (69%)
 create mode 100644 execution/evm/sha3/LICENSE
 create mode 100644 execution/evm/sha3/PATENTS
 rename {manager/burrow-mint => execution}/evm/sha3/keccakf.go (100%)
 rename {manager/burrow-mint => execution}/evm/sha3/sha3.go (100%)
 rename {manager/burrow-mint => execution}/evm/snative.go (62%)
 rename {manager/burrow-mint => execution}/evm/snative_test.go (76%)
 rename {manager/burrow-mint => execution}/evm/stack.go (84%)
 rename {manager/burrow-mint => execution}/evm/vm.go (67%)
 rename {manager/burrow-mint => execution}/evm/vm_test.go (65%)
 rename {manager/burrow-mint/state => execution}/execution.go (54%)
 create mode 100644 execution/execution_test.go
 rename {manager/burrow-mint => execution}/namereg.go (63%)
 rename {manager/burrow-mint/state => execution}/state.go (54%)
 rename {manager/burrow-mint/state => execution}/state_test.go (51%)
 create mode 100644 execution/transactor.go
 create mode 100644 execution/tx_cache.go
 delete mode 100644 manager/burrow-mint/accounts.go
 delete mode 100644 manager/burrow-mint/burrow-mint.go
 delete mode 100644 manager/burrow-mint/evm/fake_app_state.go
 delete mode 100644 manager/burrow-mint/evm/types.go
 delete mode 100644 manager/burrow-mint/pipe.go
 delete mode 100644 manager/burrow-mint/state/block_cache.go
 delete mode 100644 manager/burrow-mint/state/common.go
 delete mode 100644 manager/burrow-mint/state/genesis_test.go
 delete mode 100644 manager/burrow-mint/state/permissions_test.go
 delete mode 100644 manager/burrow-mint/state/tx_cache.go
 delete mode 100644 manager/burrow-mint/state/tx_cache_test.go
 delete mode 100644 manager/burrow-mint/transactor.go
 delete mode 100644 manager/burrow-mint/version.go
 delete mode 100644 manager/manager.go
 delete mode 100644 manager/types/application.go
 delete mode 100644 rpc/v0/rest_server_pipe_test.go

diff --git a/definitions/pipe.go b/definitions/pipe.go
deleted file mode 100644
index 286a0623..00000000
--- a/definitions/pipe.go
+++ /dev/null
@@ -1,85 +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 definitions
-
-// TODO: [ben] This respects the old Pipe interface from burrow.
-// This made sense as a wrapper around the old Tendermint, but now
-// it strongly reflects the internal details of old Tendermint outwards
-// and provides little value as an abstraction.
-// The refactor needed here for burrow-0.12.1 is to expose a language
-// of transactions, block verification and accounts, grouping
-// these interfaces into an Engine, Communicator, NameReg, Permissions (suggestion)
-
-import (
-	account "github.com/hyperledger/burrow/account"
-	blockchain_types "github.com/hyperledger/burrow/blockchain/types"
-	consensus_types "github.com/hyperledger/burrow/consensus/types"
-	core_types "github.com/hyperledger/burrow/core/types"
-	types "github.com/hyperledger/burrow/core/types"
-	event "github.com/hyperledger/burrow/event"
-	logging_types "github.com/hyperledger/burrow/logging/types"
-	manager_types "github.com/hyperledger/burrow/manager/types"
-	"github.com/hyperledger/burrow/txs"
-)
-
-type Pipe interface {
-	Accounts() Accounts
-	Blockchain() blockchain_types.Blockchain
-	Events() event.EventEmitter
-	NameReg() NameReg
-	Transactor() Transactor
-	// Hash of Genesis state
-	GenesisHash() []byte
-	Logger() logging_types.InfoTraceLogger
-	// NOTE: [ben] added to Pipe interface on 0.12 refactor
-	GetApplication() manager_types.Application
-	SetConsensusEngine(consensusEngine consensus_types.ConsensusEngine) error
-	GetConsensusEngine() consensus_types.ConsensusEngine
-	SetBlockchain(blockchain blockchain_types.Blockchain) error
-	GetBlockchain() blockchain_types.Blockchain
-	// Support for Tendermint RPC
-	GetTendermintPipe() (TendermintPipe, error)
-}
-
-type Accounts interface {
-	GenPrivAccount() (*account.PrivAccount, error)
-	GenPrivAccountFromKey(privKey []byte) (*account.PrivAccount, error)
-	Accounts([]*event.FilterData) (*types.AccountList, error)
-	Account(address []byte) (*account.Account, error)
-	Storage(address []byte) (*types.Storage, error)
-	StorageAt(address, key []byte) (*types.StorageItem, error)
-}
-
-type NameReg interface {
-	Entry(key string) (*core_types.NameRegEntry, error)
-	Entries([]*event.FilterData) (*types.ResultListNames, error)
-}
-
-type Transactor interface {
-	Call(fromAddress, toAddress, data []byte) (*types.Call, error)
-	CallCode(fromAddress, code, data []byte) (*types.Call, error)
-	// Send(privKey, toAddress []byte, amount int64) (*types.Receipt, error)
-	// SendAndHold(privKey, toAddress []byte, amount int64) (*types.Receipt, error)
-	BroadcastTx(tx txs.Tx) (*txs.Receipt, error)
-	Transact(privKey, address, data []byte, gasLimit,
-		fee int64) (*txs.Receipt, error)
-	TransactAndHold(privKey, address, data []byte, gasLimit,
-		fee int64) (*txs.EventDataCall, error)
-	Send(privKey, toAddress []byte, amount int64) (*txs.Receipt, error)
-	SendAndHold(privKey, toAddress []byte, amount int64) (*txs.Receipt, error)
-	TransactNameReg(privKey []byte, name, data string, amount,
-		fee int64) (*txs.Receipt, error)
-	SignTx(tx txs.Tx, privAccounts []*account.PrivAccount) (txs.Tx, error)
-}
diff --git a/definitions/tendermint_pipe.go b/definitions/tendermint_pipe.go
deleted file mode 100644
index faf78788..00000000
--- a/definitions/tendermint_pipe.go
+++ /dev/null
@@ -1,77 +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 definitions
-
-import (
-	"github.com/hyperledger/burrow/account"
-	rpc_tm_types "github.com/hyperledger/burrow/rpc/tendermint/core/types"
-	"github.com/hyperledger/burrow/txs"
-)
-
-// NOTE: [ben] TendermintPipe is the additional pipe to carry over
-// the RPC exposed by old Tendermint on port `46657` (burrow-0.11.4 and before)
-// This TendermintPipe interface should be deprecated and work towards a generic
-// collection of RPC routes for burrow-1.0.0
-
-type TendermintPipe interface {
-	Pipe
-	// Events
-	// Subscribe attempts to subscribe the listener identified by listenerId to
-	// the event named event. The Event result is written to rpcResponseWriter
-	// which must be non-blocking
-	Subscribe(eventId string,
-		rpcResponseWriter func(result rpc_tm_types.BurrowResult)) (*rpc_tm_types.ResultSubscribe, error)
-	Unsubscribe(subscriptionId string) (*rpc_tm_types.ResultUnsubscribe, error)
-
-	// Net
-	Status() (*rpc_tm_types.ResultStatus, error)
-	NetInfo() (*rpc_tm_types.ResultNetInfo, error)
-	Genesis() (*rpc_tm_types.ResultGenesis, error)
-	ChainId() (*rpc_tm_types.ResultChainId, error)
-
-	// Accounts
-	GetAccount(address []byte) (*rpc_tm_types.ResultGetAccount, error)
-	ListAccounts() (*rpc_tm_types.ResultListAccounts, error)
-	GetStorage(address, key []byte) (*rpc_tm_types.ResultGetStorage, error)
-	DumpStorage(address []byte) (*rpc_tm_types.ResultDumpStorage, error)
-
-	// Call
-	Call(fromAddress, toAddress, data []byte) (*rpc_tm_types.ResultCall, error)
-	CallCode(fromAddress, code, data []byte) (*rpc_tm_types.ResultCall, error)
-
-	// TODO: [ben] deprecate as we should not allow unsafe behaviour
-	// where a user is allowed to send a private key over the wire,
-	// especially unencrypted.
-	SignTransaction(tx txs.Tx,
-		privAccounts []*account.PrivAccount) (*rpc_tm_types.ResultSignTx,
-		error)
-
-	// Name registry
-	GetName(name string) (*rpc_tm_types.ResultGetName, error)
-	ListNames() (*rpc_tm_types.ResultListNames, error)
-
-	// Memory pool
-	BroadcastTxAsync(transaction txs.Tx) (*rpc_tm_types.ResultBroadcastTx, error)
-	BroadcastTxSync(transaction txs.Tx) (*rpc_tm_types.ResultBroadcastTx, error)
-
-	// Blockchain
-	BlockchainInfo(minHeight, maxHeight, maxBlockLookback int) (*rpc_tm_types.ResultBlockchainInfo, error)
-	ListUnconfirmedTxs(maxTxs int) (*rpc_tm_types.ResultListUnconfirmedTxs, error)
-	GetBlock(height int) (*rpc_tm_types.ResultGetBlock, error)
-
-	// Consensus
-	ListValidators() (*rpc_tm_types.ResultListValidators, error)
-	DumpConsensusState() (*rpc_tm_types.ResultDumpConsensusState, error)
-}
diff --git a/execution/accounts.go b/execution/accounts.go
new file mode 100644
index 00000000..0e9d1bd1
--- /dev/null
+++ b/execution/accounts.go
@@ -0,0 +1,246 @@
+// 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 execution
+
+// Accounts is part of the pipe for BurrowMint and provides the implementation
+// for the pipe to call into the BurrowMint application
+
+import (
+	"bytes"
+	"encoding/hex"
+	"fmt"
+	"sync"
+
+	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/binary"
+	"github.com/hyperledger/burrow/event"
+)
+
+// The accounts struct has methods for working with accounts.
+type accounts struct {
+	state         acm.StateIterable
+	filterFactory *event.FilterFactory
+}
+
+// Accounts
+type AccountList struct {
+	Accounts []acm.Account `json:"accounts"`
+}
+
+// A contract account storage item.
+type StorageItem struct {
+	Key   []byte `json:"key"`
+	Value []byte `json:"value"`
+}
+
+// Account storage
+type Storage struct {
+	StorageRoot  []byte        `json:"storage_root"`
+	StorageItems []StorageItem `json:"storage_items"`
+}
+
+// TODO: [Silas] there are various notes about using mempool (which I guess translates to CheckTx cache). We need
+// to understand if this is the right thing to do, since we cannot guarantee stability of the check cache it doesn't
+// seem like the right thing to do....
+func newAccounts(state acm.StateIterable) *accounts {
+	filterFactory := event.NewFilterFactory()
+
+	filterFactory.RegisterFilterPool("code", &sync.Pool{
+		New: func() interface{} {
+			return &AccountCodeFilter{}
+		},
+	})
+
+	filterFactory.RegisterFilterPool("balance", &sync.Pool{
+		New: func() interface{} {
+			return &AccountBalanceFilter{}
+		},
+	})
+
+	return &accounts{
+		state:         state,
+		filterFactory: filterFactory,
+	}
+}
+
+// Generate a new Private Key Account.
+func (accs *accounts) GenPrivAccount() (*acm.ConcretePrivateAccount, error) {
+	pa := acm.GeneratePrivateAccount().ConcretePrivateAccount
+	return pa, nil
+}
+
+// Generate a new Private Key Account.
+func (accs *accounts) GenPrivAccountFromKey(privKey []byte) (
+	*acm.ConcretePrivateAccount, error) {
+	if len(privKey) != 64 {
+		return nil, fmt.Errorf("Private key is not 64 bytes long.")
+	}
+	fmt.Printf("PK BYTES FROM ACCOUNTS: %x\n", privKey)
+	pa := acm.GeneratePrivateAccountFromPrivateKeyBytes(privKey).ConcretePrivateAccount
+	return pa, nil
+}
+
+// Get all accounts.
+func (accs *accounts) Accounts(fda []*event.FilterData) (
+	*AccountList, error) {
+	accounts := make([]acm.Account, 0)
+	filter, err := accs.filterFactory.NewFilter(fda)
+	if err != nil {
+		return nil, fmt.Errorf("Error in query: " + err.Error())
+	}
+	accs.state.IterateAccounts(func(account acm.Account) bool {
+		if filter.Match(account) {
+			accounts = append(accounts, account)
+		}
+		return false
+	})
+	return &AccountList{accounts}, nil
+}
+
+// Get an account.
+func (accs *accounts) Account(address acm.Address) (acm.Account, error) {
+	acc, err := accs.state.GetAccount(address) // NOTE: we want to read from mempool!
+	if err != nil {
+		return nil, err
+	}
+	if acc == nil {
+		acc = accs.newAcc(address)
+	}
+	return acc, nil
+}
+
+// Get the value stored at 'key' in the account with address 'address'
+// Both the key and value is returned.
+func (accs *accounts) StorageAt(address acm.Address, key []byte) (*StorageItem,
+	error) {
+	acc, err := accs.state.GetAccount(address)
+	if err != nil {
+		return nil, err
+	}
+	if acc == nil {
+		return &StorageItem{key, []byte{}}, nil
+	}
+	value, err := accs.state.GetStorage(address, binary.LeftPadWord256(key))
+	if err != nil {
+		return nil, err
+	}
+	if value == binary.Zero256 {
+		return &StorageItem{key, []byte{}}, nil
+	}
+	return &StorageItem{key, value.UnpadLeft()}, nil
+}
+
+// Get the storage of the account with address 'address'.
+func (accs *accounts) Storage(address acm.Address) (*Storage, error) {
+	state := accs.state
+	acc, err := state.GetAccount(address)
+	if err != nil {
+		return nil, err
+	}
+	storageItems := make([]StorageItem, 0)
+	if acc == nil {
+		return &Storage{nil, storageItems}, nil
+	}
+	accs.state.IterateStorage(address, func(key, value binary.Word256) bool {
+		storageItems = append(storageItems, StorageItem{
+			Key:   key.UnpadLeft(),
+			Value: value.UnpadLeft(),
+		})
+		return false
+	})
+	return &Storage{acc.StorageRoot(), storageItems}, nil
+}
+
+// Create a new account.
+func (accs *accounts) newAcc(address acm.Address) acm.Account {
+	return (&acm.ConcreteAccount{
+		Address:     address,
+		Sequence:    0,
+		Balance:     0,
+		Code:        nil,
+		StorageRoot: nil,
+	}).Account()
+}
+
+// Filter for account code.
+// Ops: == or !=
+// Could be used to match against nil, to see if an account is a contract account.
+type AccountCodeFilter struct {
+	op    string
+	value []byte
+	match func([]byte, []byte) bool
+}
+
+func (this *AccountCodeFilter) Configure(fd *event.FilterData) error {
+	op := fd.Op
+	val, err := hex.DecodeString(fd.Value)
+
+	if err != nil {
+		return fmt.Errorf("Wrong value type.")
+	}
+	if op == "==" {
+		this.match = func(a, b []byte) bool {
+			return bytes.Equal(a, b)
+		}
+	} else if op == "!=" {
+		this.match = func(a, b []byte) bool {
+			return !bytes.Equal(a, b)
+		}
+	} else {
+		return fmt.Errorf("Op: " + this.op + " is not supported for 'code' filtering")
+	}
+	this.op = op
+	this.value = val
+	return nil
+}
+
+func (this *AccountCodeFilter) Match(v interface{}) bool {
+	acc, ok := v.(acm.Account)
+	if !ok {
+		return false
+	}
+	return this.match(acc.Code(), this.value)
+}
+
+// Filter for account balance.
+// Ops: All
+type AccountBalanceFilter struct {
+	op    string
+	value uint64
+	match func(uint64, uint64) bool
+}
+
+func (this *AccountBalanceFilter) Configure(fd *event.FilterData) error {
+	val, err := event.ParseNumberValue(fd.Value)
+	if err != nil {
+		return err
+	}
+	match, err2 := event.GetRangeFilter(fd.Op, "balance")
+	if err2 != nil {
+		return err2
+	}
+	this.match = match
+	this.op = fd.Op
+	this.value = uint64(val)
+	return nil
+}
+
+func (this *AccountBalanceFilter) Match(v interface{}) bool {
+	acc, ok := v.(acm.Account)
+	if !ok {
+		return false
+	}
+	return this.match(acc.Balance(), this.value)
+}
diff --git a/execution/block_cache.go b/execution/block_cache.go
new file mode 100644
index 00000000..3c83e29e
--- /dev/null
+++ b/execution/block_cache.go
@@ -0,0 +1,386 @@
+// 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 execution
+
+import (
+	"bytes"
+	"fmt"
+	"sort"
+
+	acm "github.com/hyperledger/burrow/account"
+	. "github.com/hyperledger/burrow/binary"
+
+	"sync"
+
+	"github.com/tendermint/merkleeyes/iavl"
+	dbm "github.com/tendermint/tmlibs/db"
+	"github.com/tendermint/tmlibs/merkle"
+)
+
+func makeStorage(db dbm.DB, root []byte) merkle.Tree {
+	storage := iavl.NewIAVLTree(1024, db)
+	storage.Load(root)
+	return storage
+}
+
+var _ acm.StateWriter = &BlockCache{}
+
+var _ acm.StateIterable = &BlockCache{}
+
+// TODO: BlockCache badly needs a rewrite to remove database sharing with State and make it communicate using the
+// Account interfaces like a proper person. As well as other oddities of decoupled storage and account state
+
+// The blockcache helps prevent unnecessary IAVLTree updates and garbage generation.
+type BlockCache struct {
+	// We currently provide the RPC layer with access to read-only access to BlockCache via the StateIterable interface
+	// on BatchExecutor. However since read-only operations generate writes to the BlockCache in the current design
+	// we need a mutex here. Otherwise BlockCache ought to be used within a component that is responsible for serialising
+	// the operations on the BlockCache.
+	sync.RWMutex
+	db       dbm.DB
+	backend  *State
+	accounts map[acm.Address]accountInfo
+	storages map[acm.Address]map[Word256]storageInfo
+	names    map[string]nameInfo
+}
+
+func NewBlockCache(backend *State) *BlockCache {
+	return &BlockCache{
+		// TODO: This is bad and probably the cause of various panics. Accounts themselves are written
+		// to the State 'backend' but updates to storage just skip that and write directly to the database
+		db:       backend.db,
+		backend:  backend,
+		accounts: make(map[acm.Address]accountInfo),
+		storages: make(map[acm.Address]map[Word256]storageInfo),
+		names:    make(map[string]nameInfo),
+	}
+}
+
+func (cache *BlockCache) State() *State {
+	return cache.backend
+}
+
+//-------------------------------------
+// BlockCache.account
+
+func (cache *BlockCache) GetAccount(addr acm.Address) (acm.Account, error) {
+	acc, _, removed, _ := cache.accounts[addr].unpack()
+	if removed {
+		return nil, nil
+	} else if acc != nil {
+		return acc, nil
+	} else {
+		acc, err := cache.backend.GetAccount(addr)
+		if err != nil {
+			return nil, err
+		}
+		cache.Lock()
+		defer cache.Unlock()
+		cache.accounts[addr] = accountInfo{acc, nil, false, false}
+		return acc, nil
+	}
+}
+
+func (cache *BlockCache) UpdateAccount(acc acm.Account) error {
+	cache.Lock()
+	defer cache.Unlock()
+	addr := acc.Address()
+	_, storage, removed, _ := cache.accounts[addr].unpack()
+	if removed {
+		return fmt.Errorf("UpdateAccount on a removed account %s", addr)
+	}
+	cache.accounts[addr] = accountInfo{acc, storage, false, true}
+	return nil
+}
+
+func (cache *BlockCache) RemoveAccount(addr acm.Address) error {
+	cache.Lock()
+	defer cache.Unlock()
+	_, _, removed, _ := cache.accounts[addr].unpack()
+	if removed {
+		return fmt.Errorf("RemoveAccount on a removed account %s", addr)
+	}
+	cache.accounts[addr] = accountInfo{nil, nil, true, false}
+	return nil
+}
+
+func (cache *BlockCache) IterateAccounts(consumer func(acm.Account) (stop bool)) (bool, error) {
+	cache.RLock()
+	defer cache.RUnlock()
+	for _, info := range cache.accounts {
+		if consumer(info.account) {
+			return true, nil
+		}
+	}
+	return cache.backend.IterateAccounts(consumer)
+}
+
+// BlockCache.account
+//-------------------------------------
+// BlockCache.storage
+
+func (cache *BlockCache) GetStorage(addr acm.Address, key Word256) (Word256, error) {
+	// Check cache
+	cache.RLock()
+	info, ok := cache.lookupStorage(addr, key)
+	cache.RUnlock()
+	if ok {
+		return info.value, nil
+	}
+	// Get or load storage
+	cache.RLock()
+	acc, storage, removed, dirty := cache.accounts[addr].unpack()
+	cache.RUnlock()
+	if removed {
+		return Zero256, fmt.Errorf("GetStorage on a removed account %s", addr)
+	}
+	cache.Lock()
+	defer cache.Unlock()
+
+	if acc != nil && storage == nil {
+		storage = makeStorage(cache.db, acc.StorageRoot())
+		cache.accounts[addr] = accountInfo{acc, storage, false, dirty}
+	} else if acc == nil {
+		return Zero256, nil
+	}
+	// Load and set cache
+	_, val, _ := storage.Get(key.Bytes())
+	value := LeftPadWord256(val)
+	cache.setStorage(addr, key, storageInfo{value, false})
+	return value, nil
+}
+
+// NOTE: Set value to zero to removed from the trie.
+func (cache *BlockCache) SetStorage(addr acm.Address, key Word256, value Word256) error {
+	cache.Lock()
+	defer cache.Unlock()
+	_, _, removed, _ := cache.accounts[addr].unpack()
+	if removed {
+		return fmt.Errorf("SetStorage on a removed account %s", addr)
+	}
+	cache.setStorage(addr, key, storageInfo{value, true})
+	return nil
+}
+
+func (cache *BlockCache) IterateStorage(address acm.Address, consumer func(key, value Word256) (stop bool)) (bool, error) {
+	cache.RLock()
+	defer cache.RUnlock()
+	// Try cache first for early exit
+	for key, info := range cache.storages[address] {
+		if consumer(key, info.value) {
+			return true, nil
+		}
+	}
+
+	return cache.backend.IterateStorage(address, consumer)
+}
+
+// BlockCache.storage
+//-------------------------------------
+// BlockCache.names
+
+func (cache *BlockCache) GetNameRegEntry(name string) *NameRegEntry {
+	cache.RLock()
+	entry, removed, _ := cache.names[name].unpack()
+	cache.RUnlock()
+	if removed {
+		return nil
+	} else if entry != nil {
+		return entry
+	} else {
+		entry = cache.backend.GetNameRegEntry(name)
+		cache.Lock()
+		cache.names[name] = nameInfo{entry, false, false}
+		cache.Unlock()
+		return entry
+	}
+}
+
+func (cache *BlockCache) UpdateNameRegEntry(entry *NameRegEntry) {
+	cache.Lock()
+	defer cache.Unlock()
+	cache.names[entry.Name] = nameInfo{entry, false, true}
+}
+
+func (cache *BlockCache) RemoveNameRegEntry(name string) {
+	cache.Lock()
+	defer cache.Unlock()
+	_, removed, _ := cache.names[name].unpack()
+	if removed {
+		panic("RemoveNameRegEntry on a removed entry")
+	}
+	cache.names[name] = nameInfo{nil, true, false}
+}
+
+// BlockCache.names
+//-------------------------------------
+
+// CONTRACT the updates are in deterministic order.
+func (cache *BlockCache) Sync() {
+	cache.Lock()
+	defer cache.Unlock()
+	// Determine order for storage updates
+	// The address comes first so it'll be grouped.
+	storageKeys := make([]Tuple256, 0, len(cache.storages))
+	for address, keyInfoMap := range cache.storages {
+		for key, _ := range keyInfoMap {
+			storageKeys = append(storageKeys, Tuple256{First: address.Word256(), Second: key})
+		}
+	}
+	Tuple256Slice(storageKeys).Sort()
+
+	// Update storage for all account/key.
+	// Later we'll iterate over all the users and save storage + update storage root.
+	var (
+		curAddr       acm.Address
+		curAcc        acm.Account
+		curAccRemoved bool
+		curStorage    merkle.Tree
+	)
+	for _, storageKey := range storageKeys {
+		addrWord256, key := Tuple256Split(storageKey)
+		addr := acm.AddressFromWord256(addrWord256)
+		if addr != curAddr || curAcc == nil {
+			acc, storage, removed, _ := cache.accounts[addr].unpack()
+			if !removed && storage == nil {
+				storage = makeStorage(cache.db, acc.StorageRoot())
+			}
+			curAddr = addr
+			curAcc = acc
+			curAccRemoved = removed
+			curStorage = storage
+		}
+		if curAccRemoved {
+			continue
+		}
+		value, dirty := cache.storages[acm.AddressFromWord256(storageKey.First)][storageKey.Second].unpack()
+		if !dirty {
+			continue
+		}
+		if value.IsZero() {
+			curStorage.Remove(key.Bytes())
+		} else {
+			curStorage.Set(key.Bytes(), value.Bytes())
+			cache.accounts[addr] = accountInfo{curAcc, curStorage, false, true}
+		}
+	}
+
+	// Determine order for accounts
+	addrs := []acm.Address{}
+	for addr := range cache.accounts {
+		addrs = append(addrs, addr)
+	}
+	sort.Slice(addrs, func(i, j int) bool {
+		return addrs[i].String() < addrs[j].String()
+	})
+
+	// Update or delete accounts.
+	for _, addr := range addrs {
+		acc, storage, removed, dirty := cache.accounts[addr].unpack()
+		if removed {
+			cache.backend.RemoveAccount(addr)
+		} else {
+			if acc == nil {
+				continue
+			}
+			if storage != nil {
+				newStorageRoot := storage.Save()
+				if !bytes.Equal(newStorageRoot, acc.StorageRoot()) {
+					acc = acm.AsMutableAccount(acc).SetStorageRoot(newStorageRoot)
+					dirty = true
+				}
+			}
+			if dirty {
+				cache.backend.UpdateAccount(acc)
+			}
+		}
+	}
+
+	// Determine order for names
+	// note names may be of any length less than some limit
+	nameStrs := []string{}
+	for nameStr := range cache.names {
+		nameStrs = append(nameStrs, nameStr)
+	}
+	sort.Strings(nameStrs)
+
+	// Update or delete names.
+	for _, nameStr := range nameStrs {
+		entry, removed, dirty := cache.names[nameStr].unpack()
+		if removed {
+			removed := cache.backend.RemoveNameRegEntry(nameStr)
+			if !removed {
+				panic(fmt.Sprintf("Could not remove namereg entry to be removed: %s", nameStr))
+			}
+		} else {
+			if entry == nil {
+				continue
+			}
+			if dirty {
+				cache.backend.UpdateNameRegEntry(entry)
+			}
+		}
+	}
+}
+
+func (cache *BlockCache) lookupStorage(address acm.Address, key Word256) (storageInfo, bool) {
+	keyInfoMap, ok := cache.storages[address]
+	if !ok {
+		return storageInfo{}, false
+	}
+	info, ok := keyInfoMap[key]
+	return info, ok
+}
+
+func (cache *BlockCache) setStorage(address acm.Address, key Word256, info storageInfo) {
+	keyInfoMap, ok := cache.storages[address]
+	if !ok {
+		keyInfoMap = make(map[Word256]storageInfo)
+		cache.storages[address] = keyInfoMap
+	}
+	keyInfoMap[key] = info
+}
+
+//-----------------------------------------------------------------------------
+
+type accountInfo struct {
+	account acm.Account
+	storage merkle.Tree
+	removed bool
+	dirty   bool
+}
+
+func (accInfo accountInfo) unpack() (acm.Account, merkle.Tree, bool, bool) {
+	return accInfo.account, accInfo.storage, accInfo.removed, accInfo.dirty
+}
+
+type storageInfo struct {
+	value Word256
+	dirty bool
+}
+
+func (stjInfo storageInfo) unpack() (Word256, bool) {
+	return stjInfo.value, stjInfo.dirty
+}
+
+type nameInfo struct {
+	name    *NameRegEntry
+	removed bool
+	dirty   bool
+}
+
+func (nInfo nameInfo) unpack() (*NameRegEntry, bool, bool) {
+	return nInfo.name, nInfo.removed, nInfo.dirty
+}
diff --git a/execution/events/events.go b/execution/events/events.go
new file mode 100644
index 00000000..266a1860
--- /dev/null
+++ b/execution/events/events.go
@@ -0,0 +1,51 @@
+package events
+
+import (
+	"encoding/json"
+	"fmt"
+
+	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/txs"
+)
+
+func EventStringAccInput(addr acm.Address) string  { return fmt.Sprintf("Acc/%s/Input", addr) }
+func EventStringAccOutput(addr acm.Address) string { return fmt.Sprintf("Acc/%s/Output", addr) }
+func EventStringNameReg(name string) string        { return fmt.Sprintf("NameReg/%s", name) }
+func EventStringPermissions(name string) string    { return fmt.Sprintf("Permissions/%s", name) }
+func EventStringBond() string                      { return "Bond" }
+func EventStringUnbond() string                    { return "Unbond" }
+func EventStringRebond() string                    { return "Rebond" }
+
+// All txs fire EventDataTx, but only CallTx might have Return or Exception
+type EventDataTx struct {
+	Tx        txs.Tx `json:"tx"`
+	Return    []byte `json:"return"`
+	Exception string `json:"exception"`
+}
+
+type eventDataTx struct {
+	Tx        txs.Wrapper `json:"tx"`
+	Return    []byte      `json:"return"`
+	Exception string      `json:"exception"`
+}
+
+func (edTx EventDataTx) MarshalJSON() ([]byte, error) {
+	model := eventDataTx{
+		Tx:        txs.Wrap(edTx.Tx),
+		Exception: edTx.Exception,
+		Return:    edTx.Return,
+	}
+	return json.Marshal(model)
+}
+
+func (edTx *EventDataTx) UnmarshalJSON(data []byte) error {
+	model := new(eventDataTx)
+	err := json.Unmarshal(data, model)
+	if err != nil {
+		return err
+	}
+	edTx.Tx = model.Tx.Unwrap()
+	edTx.Return = model.Return
+	edTx.Exception = model.Exception
+	return nil
+}
diff --git a/manager/burrow-mint/evm/abi/types.go b/execution/evm/abi/types.go
similarity index 100%
rename from manager/burrow-mint/evm/abi/types.go
rename to execution/evm/abi/types.go
diff --git a/execution/evm/accounts.go b/execution/evm/accounts.go
new file mode 100644
index 00000000..19735838
--- /dev/null
+++ b/execution/evm/accounts.go
@@ -0,0 +1,25 @@
+package evm
+
+import (
+	acm "github.com/hyperledger/burrow/account"
+	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) acm.MutableAccount {
+	// Generate an address
+	sequence := creator.Sequence()
+	creator.IncSequence()
+
+	addr := acm.NewContractAddress(creator.Address(), sequence)
+
+	// Create account from address.
+	return (&acm.ConcreteAccount{
+		Address:     addr,
+		Balance:     0,
+		Code:        nil,
+		Sequence:    0,
+		Permissions: permissions,
+	}).MutableAccount()
+}
diff --git a/execution/evm/asm/bc/helpers.go b/execution/evm/asm/bc/helpers.go
new file mode 100644
index 00000000..4d8058d1
--- /dev/null
+++ b/execution/evm/asm/bc/helpers.go
@@ -0,0 +1,68 @@
+package bc
+
+import (
+	"fmt"
+
+	"github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/binary"
+	"github.com/hyperledger/burrow/execution/evm/asm"
+)
+
+// Convenience function to allow us to mix bytes, ints, and OpCodes that
+// represent bytes in an EVM assembly code to make assembly more readable.
+// Also allows us to splice together assembly
+// fragments because any []byte arguments are flattened in the result.
+func Splice(bytelikes ...interface{}) []byte {
+	bytes := make([]byte, len(bytelikes))
+	for i, bytelike := range bytelikes {
+		switch b := bytelike.(type) {
+		case byte:
+			bytes[i] = b
+		case asm.OpCode:
+			bytes[i] = byte(b)
+		case int:
+			bytes[i] = byte(b)
+			if int(bytes[i]) != b {
+				panic(fmt.Sprintf("The int %v does not fit inside a byte", b))
+			}
+		case int64:
+			bytes[i] = byte(b)
+			if int64(bytes[i]) != b {
+				panic(fmt.Sprintf("The int64 %v does not fit inside a byte", b))
+			}
+		case uint64:
+			bytes[i] = byte(b)
+			if uint64(bytes[i]) != b {
+				panic(fmt.Sprintf("The uint64 %v does not fit inside a byte", b))
+			}
+		case binary.Word256:
+			return Concat(bytes[:i], b[:], Splice(bytelikes[i+1:]...))
+		case binary.Word160:
+			return Concat(bytes[:i], b[:], Splice(bytelikes[i+1:]...))
+		case account.Address:
+			return Concat(bytes[:i], b[:], Splice(bytelikes[i+1:]...))
+		case []byte:
+			// splice
+			return Concat(bytes[:i], b, Splice(bytelikes[i+1:]...))
+		default:
+			panic(fmt.Errorf("could not convert %s to a byte or sequence of bytes", bytelike))
+		}
+	}
+	return bytes
+}
+
+func Concat(bss ...[]byte) []byte {
+	offset := 0
+	for _, bs := range bss {
+		offset += len(bs)
+	}
+	bytes := make([]byte, offset)
+	offset = 0
+	for _, bs := range bss {
+		for i, b := range bs {
+			bytes[offset+i] = b
+		}
+		offset += len(bs)
+	}
+	return bytes
+}
diff --git a/manager/burrow-mint/evm/opcodes/opcodes.go b/execution/evm/asm/opcodes.go
similarity index 81%
rename from manager/burrow-mint/evm/opcodes/opcodes.go
rename to execution/evm/asm/opcodes.go
index a8139d82..bbe5dec9 100644
--- a/manager/burrow-mint/evm/opcodes/opcodes.go
+++ b/execution/evm/asm/opcodes.go
@@ -12,12 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package opcodes
+package asm
 
 import (
 	"fmt"
 
-	"github.com/hyperledger/burrow/word256"
 	"gopkg.in/fatih/set.v0"
 )
 
@@ -341,6 +340,11 @@ var opCodeToString = map[OpCode]string{
 	SELFDESTRUCT: "SELFDESTRUCT",
 }
 
+func OpCodeName(op OpCode) (name string, isOpcode bool) {
+	name, isOpcode = opCodeToString[op]
+	return name, isOpcode
+}
+
 func (o OpCode) String() string {
 	str := opCodeToString[o]
 	if len(str) == 0 {
@@ -368,53 +372,3 @@ func AnalyzeJumpDests(code []byte) (dests *set.Set) {
 	}
 	return
 }
-
-// Convenience function to allow us to mix bytes, ints, and OpCodes that
-// represent bytes in an EVM assembly code to make assembly more readable.
-// Also allows us to splice together assembly
-// fragments because any []byte arguments are flattened in the result.
-func Bytecode(bytelikes ...interface{}) []byte {
-	bytes := make([]byte, len(bytelikes))
-	for i, bytelike := range bytelikes {
-		switch b := bytelike.(type) {
-		case byte:
-			bytes[i] = b
-		case OpCode:
-			bytes[i] = byte(b)
-		case int:
-			bytes[i] = byte(b)
-			if int(bytes[i]) != b {
-				panic(fmt.Sprintf("The int %v does not fit inside a byte", b))
-			}
-		case int64:
-			bytes[i] = byte(b)
-			if int64(bytes[i]) != b {
-				panic(fmt.Sprintf("The int64 %v does not fit inside a byte", b))
-			}
-		case word256.Word256:
-			return Concat(bytes[:i], b[:], Bytecode(bytelikes[i+1:]...))
-		case []byte:
-			// splice
-			return Concat(bytes[:i], b, Bytecode(bytelikes[i+1:]...))
-		default:
-			panic("Only byte-like codes (and []byte sequences) can be used to form bytecode")
-		}
-	}
-	return bytes
-}
-
-func Concat(bss ...[]byte) []byte {
-	offset := 0
-	for _, bs := range bss {
-		offset += len(bs)
-	}
-	bytes := make([]byte, offset)
-	offset = 0
-	for _, bs := range bss {
-		for i, b := range bs {
-			bytes[offset+i] = b
-		}
-		offset += len(bs)
-	}
-	return bytes
-}
diff --git a/manager/burrow-mint/evm/common.go b/execution/evm/common.go
similarity index 98%
rename from manager/burrow-mint/evm/common.go
rename to execution/evm/common.go
index fbbd4c51..e8fb7444 100644
--- a/manager/burrow-mint/evm/common.go
+++ b/execution/evm/common.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package vm
+package evm
 
 import (
 	"math/big"
diff --git a/execution/evm/events/events.go b/execution/evm/events/events.go
new file mode 100644
index 00000000..4bc7a323
--- /dev/null
+++ b/execution/evm/events/events.go
@@ -0,0 +1,54 @@
+// 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 events
+
+import (
+	"fmt"
+
+	acm "github.com/hyperledger/burrow/account"
+	. "github.com/hyperledger/burrow/binary"
+)
+
+// Functions to generate eventId strings
+
+func EventStringAccCall(addr acm.Address) string  { return fmt.Sprintf("Acc/%s/Call", addr) }
+func EventStringLogEvent(addr acm.Address) string { return fmt.Sprintf("Log/%s", addr) }
+
+//----------------------------------------
+
+// EventDataCall fires when we call a contract, and when a contract calls another contract
+type EventDataCall struct {
+	CallData  *CallData   `json:"call_data"`
+	Origin    acm.Address `json:"origin"`
+	TxID      []byte      `json:"tx_id"`
+	Return    []byte      `json:"return"`
+	Exception string      `json:"exception"`
+}
+
+type CallData struct {
+	Caller acm.Address `json:"caller"`
+	Callee acm.Address `json:"callee"`
+	Data   []byte      `json:"data"`
+	Value  uint64      `json:"value"`
+	Gas    uint64      `json:"gas"`
+}
+
+// EventDataLog fires when a contract executes the LOG opcode
+type EventDataLog struct {
+	Address acm.Address `json:"address"`
+	Topics  []Word256   `json:"topics"`
+	Data    []byte      `json:"data"`
+	Height  uint64      `json:"height"`
+}
diff --git a/execution/evm/fake_app_state.go b/execution/evm/fake_app_state.go
new file mode 100644
index 00000000..09a985ca
--- /dev/null
+++ b/execution/evm/fake_app_state.go
@@ -0,0 +1,87 @@
+// 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 evm
+
+import (
+	"fmt"
+
+	"bytes"
+
+	acm "github.com/hyperledger/burrow/account"
+	. "github.com/hyperledger/burrow/binary"
+)
+
+type FakeAppState struct {
+	accounts map[acm.Address]acm.Account
+	storage  map[string]Word256
+}
+
+var _ acm.StateWriter = &FakeAppState{}
+
+func (fas *FakeAppState) GetAccount(addr acm.Address) (acm.Account, error) {
+	account := fas.accounts[addr]
+	return account, nil
+}
+
+func (fas *FakeAppState) UpdateAccount(account acm.Account) error {
+	fas.accounts[account.Address()] = account
+	return nil
+}
+
+func (fas *FakeAppState) RemoveAccount(address acm.Address) error {
+	_, ok := fas.accounts[address]
+	if !ok {
+		panic(fmt.Sprintf("Invalid account addr: %s", address))
+	} else {
+		// Remove account
+		delete(fas.accounts, address)
+	}
+	return nil
+}
+
+func (fas *FakeAppState) GetStorage(addr acm.Address, key Word256) (Word256, error) {
+	_, ok := fas.accounts[addr]
+	if !ok {
+		panic(fmt.Sprintf("Invalid account addr: %s", addr))
+	}
+
+	value, ok := fas.storage[addr.String()+key.String()]
+	if ok {
+		return value, nil
+	} else {
+		return Zero256, nil
+	}
+}
+
+func (fas *FakeAppState) SetStorage(addr acm.Address, key Word256, value Word256) error {
+	_, ok := fas.accounts[addr]
+	if !ok {
+
+		fmt.Println("\n\n", fas.accountsDump())
+		panic(fmt.Sprintf("Invalid account addr: %s", addr))
+	}
+
+	fas.storage[addr.String()+key.String()] = value
+	return nil
+}
+
+func (fas *FakeAppState) accountsDump() string {
+	buf := new(bytes.Buffer)
+	fmt.Fprint(buf, "Dumping accounts...", "\n")
+	for _, acc := range fas.accounts {
+		fmt.Fprint(buf, acc.Address().String(), "\n")
+	}
+	return buf.String()
+}
diff --git a/manager/burrow-mint/evm/gas.go b/execution/evm/gas.go
similarity index 62%
rename from manager/burrow-mint/evm/gas.go
rename to execution/evm/gas.go
index 9ffc5e56..a764a5a5 100644
--- a/manager/burrow-mint/evm/gas.go
+++ b/execution/evm/gas.go
@@ -12,21 +12,21 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package vm
+package evm
 
 const (
-	GasSha3          int64 = 1
-	GasGetAccount    int64 = 1
-	GasStorageUpdate int64 = 1
+	GasSha3          uint64 = 1
+	GasGetAccount    uint64 = 1
+	GasStorageUpdate uint64 = 1
 
-	GasBaseOp  int64 = 0 // TODO: make this 1
-	GasStackOp int64 = 1
+	GasBaseOp  uint64 = 0 // TODO: make this 1
+	GasStackOp uint64 = 1
 
-	GasEcRecover     int64 = 1
-	GasSha256Word    int64 = 1
-	GasSha256Base    int64 = 1
-	GasRipemd160Word int64 = 1
-	GasRipemd160Base int64 = 1
-	GasIdentityWord  int64 = 1
-	GasIdentityBase  int64 = 1
+	GasEcRecover     uint64 = 1
+	GasSha256Word    uint64 = 1
+	GasSha256Base    uint64 = 1
+	GasRipemd160Word uint64 = 1
+	GasRipemd160Base uint64 = 1
+	GasIdentityWord  uint64 = 1
+	GasIdentityBase  uint64 = 1
 )
diff --git a/manager/burrow-mint/evm/log_event_test.go b/execution/evm/log_event_test.go
similarity index 65%
rename from manager/burrow-mint/evm/log_event_test.go
rename to execution/evm/log_event_test.go
index 7dd569a6..76b7dc75 100644
--- a/manager/burrow-mint/evm/log_event_test.go
+++ b/execution/evm/log_event_test.go
@@ -12,21 +12,23 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package vm
+package evm
 
 import (
 	"bytes"
 	"reflect"
 	"testing"
 
-	. "github.com/hyperledger/burrow/manager/burrow-mint/evm/opcodes"
-	"github.com/hyperledger/burrow/txs"
-	. "github.com/hyperledger/burrow/word256"
-	"github.com/tendermint/go-events"
+	acm "github.com/hyperledger/burrow/account"
+	. "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/logging/loggers"
 )
 
 var expectedData = []byte{0x10}
-var expectedHeight int64 = 0
+var expectedHeight uint64 = 0
 var expectedTopics = []Word256{
 	Int64ToWord256(1),
 	Int64ToWord256(2),
@@ -38,28 +40,24 @@ func TestLog4(t *testing.T) {
 
 	st := newAppState()
 	// Create accounts
-	account1 := &Account{
-		Address: LeftPadWord256(makeBytes(20)),
-	}
-	account2 := &Account{
-		Address: LeftPadWord256(makeBytes(20)),
-	}
-	st.accounts[account1.Address.String()] = account1
-	st.accounts[account2.Address.String()] = account2
+	account1 := acm.ConcreteAccount{
+		Address: acm.Address{1, 3, 5, 7, 9},
+	}.MutableAccount()
+	account2 := acm.ConcreteAccount{
+		Address: acm.Address{2, 4, 6, 8, 10},
+	}.MutableAccount()
+	st.accounts[account1.Address()] = account1
+	st.accounts[account2.Address()] = account2
 
-	ourVm := NewVM(st, DefaultDynamicMemoryProvider, newParams(), Zero256, nil)
+	ourVm := NewVM(st, DefaultDynamicMemoryProvider, newParams(), acm.ZeroAddress, nil, logger)
 
-	eventSwitch := events.NewEventSwitch()
-	_, err := eventSwitch.Start()
-	if err != nil {
-		t.Errorf("Failed to start eventSwitch: %v", err)
-	}
-	eventID := txs.EventStringLogEvent(account2.Address.Postfix(20))
+	eventSwitch := event.NewEmitter(loggers.NewNoopInfoTraceLogger())
+	eventID := events.EventStringLogEvent(account2.Address())
 
 	doneChan := make(chan struct{}, 1)
 
-	eventSwitch.AddListenerForEvent("test", eventID, func(event events.EventData) {
-		logEvent := event.(txs.EventDataLog)
+	eventSwitch.Subscribe("test", eventID, func(eventData event.AnyEventData) {
+		logEvent := eventData.EventDataLog()
 		// No need to test address as this event would not happen if it wasn't correct
 		if !reflect.DeepEqual(logEvent.Topics, expectedTopics) {
 			t.Errorf("Event topics are wrong. Got: %v. Expected: %v", logEvent.Topics, expectedTopics)
@@ -75,7 +73,7 @@ func TestLog4(t *testing.T) {
 
 	ourVm.SetFireable(eventSwitch)
 
-	var gas int64 = 100000
+	var gas uint64 = 100000
 
 	mstore8 := byte(MSTORE8)
 	push1 := byte(PUSH1)
@@ -96,7 +94,7 @@ func TestLog4(t *testing.T) {
 		stop,
 	}
 
-	_, err = ourVm.Call(account1, account2, code, []byte{}, 0, &gas)
+	_, err := ourVm.Call(account1, account2, code, []byte{}, 0, &gas)
 	<-doneChan
 	if err != nil {
 		t.Fatal(err)
diff --git a/manager/burrow-mint/evm/memory.go b/execution/evm/memory.go
similarity index 91%
rename from manager/burrow-mint/evm/memory.go
rename to execution/evm/memory.go
index fc24dbd7..6eb8456c 100644
--- a/manager/burrow-mint/evm/memory.go
+++ b/execution/evm/memory.go
@@ -1,4 +1,4 @@
-package vm
+package evm
 
 import (
 	"fmt"
@@ -12,7 +12,7 @@ const (
 
 // Change the length of this zero array to tweak the size of the block of zeros
 // written to the backing slice at a time when it is grown. A larger number may
-// lead to less calls to append to achieve the desired capacity although it is
+// lead to fewer calls to append to achieve the desired capacity although it is
 // unlikely to make a lot of difference.
 var zeroBlock []byte = make([]byte, 32)
 
@@ -86,9 +86,9 @@ func (mem *dynamicMemory) Capacity() int64 {
 // memory (will not shrink).
 func (mem *dynamicMemory) ensureCapacity(newCapacity int64) error {
 	if newCapacity > math.MaxInt32 {
-		// If we ever did want to then we would need to maintain multiple pages
-		// of memory
-		return fmt.Errorf("Cannot address memory beyond a maximum index "+
+		// If we ever did want more than an int32 of space then we would need to
+		// maintain multiple pages of memory
+		return fmt.Errorf("cannot address memory beyond a maximum index "+
 			"of Int32 type (%v bytes)", math.MaxInt32)
 	}
 	newCapacityInt := int(newCapacity)
@@ -97,7 +97,7 @@ func (mem *dynamicMemory) ensureCapacity(newCapacity int64) error {
 		return nil
 	}
 	if newCapacity > mem.maximumCapacity {
-		return fmt.Errorf("Cannot grow memory because it would exceed the "+
+		return fmt.Errorf("cannot grow memory because it would exceed the "+
 			"current maximum limit of %v bytes", mem.maximumCapacity)
 	}
 	// Ensure the backing array of slice is big enough
diff --git a/manager/burrow-mint/evm/memory_test.go b/execution/evm/memory_test.go
similarity index 99%
rename from manager/burrow-mint/evm/memory_test.go
rename to execution/evm/memory_test.go
index 2477b32d..923cdda4 100644
--- a/manager/burrow-mint/evm/memory_test.go
+++ b/execution/evm/memory_test.go
@@ -1,4 +1,4 @@
-package vm
+package evm
 
 import (
 	"testing"
diff --git a/manager/burrow-mint/evm/native.go b/execution/evm/native.go
similarity index 69%
rename from manager/burrow-mint/evm/native.go
rename to execution/evm/native.go
index 17478055..198977c4 100644
--- a/manager/burrow-mint/evm/native.go
+++ b/execution/evm/native.go
@@ -12,13 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package vm
+package evm
 
 import (
 	"crypto/sha256"
 
-	. "github.com/hyperledger/burrow/word256"
-
+	acm "github.com/hyperledger/burrow/account"
+	. "github.com/hyperledger/burrow/binary"
+	logging_types "github.com/hyperledger/burrow/logging/types"
 	"golang.org/x/crypto/ripemd160"
 )
 
@@ -52,10 +53,11 @@ func registerNativeContracts() {
 
 //-----------------------------------------------------------------------------
 
-type NativeContract func(appState AppState, caller *Account, input []byte, gas *int64) (output []byte, err error)
+type NativeContract func(state acm.StateWriter, caller acm.Account, input []byte, gas *uint64,
+	logger logging_types.InfoTraceLogger) (output []byte, err error)
 
 /* Removed due to C dependency
-func ecrecoverFunc(appState AppState, caller *Account, input []byte, gas *int64) (output []byte, err error) {
+func ecrecoverFunc(state State, caller *acm.Account, input []byte, gas *int64) (output []byte, err error) {
 	// Deduct gas
 	gasRequired := GasEcRecover
 	if *gas < gasRequired {
@@ -77,9 +79,10 @@ func ecrecoverFunc(appState AppState, caller *Account, input []byte, gas *int64)
 }
 */
 
-func sha256Func(appState AppState, caller *Account, input []byte, gas *int64) (output []byte, err error) {
+func sha256Func(state acm.StateWriter, caller acm.Account, input []byte, gas *uint64,
+	logger logging_types.InfoTraceLogger) (output []byte, err error) {
 	// Deduct gas
-	gasRequired := int64((len(input)+31)/32)*GasSha256Word + GasSha256Base
+	gasRequired := uint64((len(input)+31)/32)*GasSha256Word + GasSha256Base
 	if *gas < gasRequired {
 		return nil, ErrInsufficientGas
 	} else {
@@ -92,9 +95,10 @@ func sha256Func(appState AppState, caller *Account, input []byte, gas *int64) (o
 	return hasher.Sum(nil), nil
 }
 
-func ripemd160Func(appState AppState, caller *Account, input []byte, gas *int64) (output []byte, err error) {
+func ripemd160Func(state acm.StateWriter, caller acm.Account, input []byte, gas *uint64,
+	logger logging_types.InfoTraceLogger) (output []byte, err error) {
 	// Deduct gas
-	gasRequired := int64((len(input)+31)/32)*GasRipemd160Word + GasRipemd160Base
+	gasRequired := uint64((len(input)+31)/32)*GasRipemd160Word + GasRipemd160Base
 	if *gas < gasRequired {
 		return nil, ErrInsufficientGas
 	} else {
@@ -107,9 +111,10 @@ func ripemd160Func(appState AppState, caller *Account, input []byte, gas *int64)
 	return LeftPadBytes(hasher.Sum(nil), 32), nil
 }
 
-func identityFunc(appState AppState, caller *Account, input []byte, gas *int64) (output []byte, err error) {
+func identityFunc(state acm.StateWriter, caller acm.Account, input []byte, gas *uint64,
+	logger logging_types.InfoTraceLogger) (output []byte, err error) {
 	// Deduct gas
-	gasRequired := int64((len(input)+31)/32)*GasIdentityWord + GasIdentityBase
+	gasRequired := uint64((len(input)+31)/32)*GasIdentityWord + GasIdentityBase
 	if *gas < gasRequired {
 		return nil, ErrInsufficientGas
 	} else {
diff --git a/execution/evm/sha3/LICENSE b/execution/evm/sha3/LICENSE
new file mode 100644
index 00000000..6a66aea5
--- /dev/null
+++ b/execution/evm/sha3/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/execution/evm/sha3/PATENTS b/execution/evm/sha3/PATENTS
new file mode 100644
index 00000000..73309904
--- /dev/null
+++ b/execution/evm/sha3/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go.  This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation.  If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/manager/burrow-mint/evm/sha3/keccakf.go b/execution/evm/sha3/keccakf.go
similarity index 100%
rename from manager/burrow-mint/evm/sha3/keccakf.go
rename to execution/evm/sha3/keccakf.go
diff --git a/manager/burrow-mint/evm/sha3/sha3.go b/execution/evm/sha3/sha3.go
similarity index 100%
rename from manager/burrow-mint/evm/sha3/sha3.go
rename to execution/evm/sha3/sha3.go
diff --git a/manager/burrow-mint/evm/snative.go b/execution/evm/snative.go
similarity index 62%
rename from manager/burrow-mint/evm/snative.go
rename to execution/evm/snative.go
index 3f628e99..e98937ad 100644
--- a/manager/burrow-mint/evm/snative.go
+++ b/execution/evm/snative.go
@@ -12,19 +12,22 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package vm
+package evm
 
 import (
 	"fmt"
 
-	"github.com/hyperledger/burrow/common/sanity"
-	"github.com/hyperledger/burrow/manager/burrow-mint/evm/sha3"
-	ptypes "github.com/hyperledger/burrow/permission/types"
-	. "github.com/hyperledger/burrow/word256"
-
 	"strings"
 
-	"github.com/hyperledger/burrow/manager/burrow-mint/evm/abi"
+	acm "github.com/hyperledger/burrow/account"
+	. "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"
 )
 
 //
@@ -65,7 +68,7 @@ type SNativeFunctionDescription struct {
 
 func registerSNativeContracts() {
 	for _, contract := range SNativeContracts() {
-		registeredNativeContracts[contract.AddressWord256()] = contract.Dispatch
+		registeredNativeContracts[contract.Address().Word256()] = contract.Dispatch
 	}
 }
 
@@ -91,7 +94,7 @@ func SNativeContracts() map[string]*SNativeContractDescription {
 					abiArg("_role", roleTypeName),
 				},
 				abiReturn("result", abi.BoolTypeName),
-				ptypes.AddRole,
+				permission.AddRole,
 				addRole},
 
 			&SNativeFunctionDescription{`
@@ -106,7 +109,7 @@ func SNativeContracts() map[string]*SNativeContractDescription {
 					abiArg("_role", roleTypeName),
 				},
 				abiReturn("result", abi.BoolTypeName),
-				ptypes.RmRole,
+				permission.RemoveRole,
 				removeRole},
 
 			&SNativeFunctionDescription{`
@@ -121,7 +124,7 @@ func SNativeContracts() map[string]*SNativeContractDescription {
 					abiArg("_role", roleTypeName),
 				},
 				abiReturn("result", abi.BoolTypeName),
-				ptypes.HasRole,
+				permission.HasRole,
 				hasRole},
 
 			&SNativeFunctionDescription{`
@@ -138,13 +141,13 @@ func SNativeContracts() map[string]*SNativeContractDescription {
 					abiArg("_set", abi.BoolTypeName),
 				},
 				abiReturn("result", permFlagTypeName),
-				ptypes.SetBase,
+				permission.SetBase,
 				setBase},
 
 			&SNativeFunctionDescription{`
 			* @notice Unsets the permissions flags for an account. Causes permissions being unset to fall through to global permissions.
-      * @param _account account address
-      * @param _permission the permissions flags to unset for the account
+      		* @param _account account address
+      		* @param _permission the permissions flags to unset for the account
 			* @return result the effective permissions flags on the account after the call
       `,
 				"unsetBase",
@@ -152,7 +155,7 @@ func SNativeContracts() map[string]*SNativeContractDescription {
 					abiArg("_account", abi.AddressTypeName),
 					abiArg("_permission", permFlagTypeName)},
 				abiReturn("result", permFlagTypeName),
-				ptypes.UnsetBase,
+				permission.UnsetBase,
 				unsetBase},
 
 			&SNativeFunctionDescription{`
@@ -166,7 +169,7 @@ func SNativeContracts() map[string]*SNativeContractDescription {
 					abiArg("_account", abi.AddressTypeName),
 					abiArg("_permission", permFlagTypeName)},
 				abiReturn("result", abi.BoolTypeName),
-				ptypes.HasBase,
+				permission.HasBase,
 				hasBase},
 
 			&SNativeFunctionDescription{`
@@ -180,7 +183,7 @@ func SNativeContracts() map[string]*SNativeContractDescription {
 					abiArg("_permission", permFlagTypeName),
 					abiArg("_set", abi.BoolTypeName)},
 				abiReturn("result", permFlagTypeName),
-				ptypes.SetGlobal,
+				permission.SetGlobal,
 				setGlobal},
 		),
 	}
@@ -190,8 +193,8 @@ func SNativeContracts() map[string]*SNativeContractDescription {
 		if _, ok := contractMap[contract.Name]; ok {
 			// If this happens we have a pseudo compile time error that will be caught
 			// on native.go init()
-			panic(fmt.Errorf("Duplicate contract with name %s defined. "+
-				"Contract names must be unique.", contract.Name))
+			panic(fmt.Errorf("duplicate contract with name %s defined. "+
+				"Contract names must be unique", contract.Name))
 		}
 		contractMap[contract.Name] = contract
 	}
@@ -208,7 +211,7 @@ func NewSNativeContract(comment, name string,
 		fid := f.ID()
 		otherF, ok := functionsByID[fid]
 		if ok {
-			panic(fmt.Errorf("Function with ID %x already defined: %s", fid,
+			panic(fmt.Errorf("function with ID %x already defined: %s", fid,
 				otherF))
 		}
 		functionsByID[fid] = f
@@ -224,8 +227,12 @@ func NewSNativeContract(comment, name string,
 // 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(appState AppState,
-	caller *Account, args []byte, gas *int64) (output []byte, err error) {
+func (contract *SNativeContractDescription) Dispatch(state acm.StateWriter, caller acm.Account,
+	args []byte, gas *uint64, logger logging_types.InfoTraceLogger) (output []byte, err error) {
+
+	logger = logger.WithPrefix(structure.ComponentKey, "SNatives").
+		With(structure.ScopeKey, "Dispatch", "contract_name", contract.Name)
+
 	if len(args) < abi.FunctionSelectorLength {
 		return nil, fmt.Errorf("SNatives dispatch requires a 4-byte function "+
 			"identifier but arguments are only %s bytes long", len(args))
@@ -236,41 +243,31 @@ func (contract *SNativeContractDescription) Dispatch(appState AppState,
 		return nil, err
 	}
 
+	logging.TraceMsg(logger, "Dispatching to function", "function_name", function.Name)
+
 	remainingArgs := args[abi.FunctionSelectorLength:]
 
 	// check if we have permission to call this function
-	if !HasPermission(appState, caller, function.PermFlag) {
-		return nil, ErrInvalidPermission{caller.Address, function.Name}
+	if !HasPermission(state, caller, function.PermFlag) {
+		return nil, ErrLacksSNativePermission{caller.Address(), function.Name}
 	}
 
 	// ensure there are enough arguments
 	if len(remainingArgs) != function.NArgs()*Word256Length {
-		return nil, fmt.Errorf("%s() takes %d arguments", function.Name,
-			function.NArgs())
+		return nil, fmt.Errorf("%s() takes %d arguments but got %d (with %d bytes unconsumed - should be 0)",
+			function.Name, function.NArgs(), len(remainingArgs)/Word256Length, len(remainingArgs)%Word256Length)
 	}
 
 	// call the function
-	return function.F(appState, caller, remainingArgs, gas)
+	return function.F(state, caller, remainingArgs, gas, logger)
 }
 
 // We define the address of an SNative contact as the last 20 bytes of the sha3
 // hash of its name
-func (contract *SNativeContractDescription) Address() abi.Address {
-	var address abi.Address
+func (contract *SNativeContractDescription) Address() (address acm.Address) {
 	hash := sha3.Sha3([]byte(contract.Name))
 	copy(address[:], hash[len(hash)-abi.AddressLength:])
-	return address
-}
-
-// Get address as a byte slice
-func (contract *SNativeContractDescription) AddressBytes() []byte {
-	address := contract.Address()
-	return address[:]
-}
-
-// Get address as a left-padded Word256
-func (contract *SNativeContractDescription) AddressWord256() Word256 {
-	return LeftPadWord256(contract.AddressBytes())
+	return
 }
 
 // Get function by calling identifier FunctionSelector
@@ -278,7 +275,7 @@ func (contract *SNativeContractDescription) FunctionByID(id abi.FunctionSelector
 	f, ok := contract.functionsByID[id]
 	if !ok {
 		return nil,
-			fmt.Errorf("Unknown SNative function with ID %x", id)
+			fmt.Errorf("unknown SNative function with ID %x", id)
 	}
 	return f, nil
 }
@@ -290,7 +287,7 @@ func (contract *SNativeContractDescription) FunctionByName(name string) (*SNativ
 			return f, nil
 		}
 	}
-	return nil, fmt.Errorf("Unknown SNative function with name %s", name)
+	return nil, fmt.Errorf("unknown SNative function with name %s", name)
 }
 
 // Get functions in order of declaration
@@ -341,142 +338,197 @@ 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(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
-	addr, permNum := returnTwoArgs(args)
-	vmAcc := appState.GetAccount(addr)
-	if vmAcc == nil {
-		return nil, fmt.Errorf("Unknown account %X", addr)
+func hasBase(state acm.StateWriter, caller acm.Account, args []byte, gas *uint64,
+	logger logging_types.InfoTraceLogger) (output []byte, err error) {
+
+	addrWord256, permNum := returnTwoArgs(args)
+	address := acm.AddressFromWord256(addrWord256)
+	acc, err := state.GetAccount(address)
+	if err != nil {
+		return nil, err
+	}
+	if acc == nil {
+		return nil, fmt.Errorf("unknown account %s", address)
 	}
 	permN := ptypes.PermFlag(Uint64FromWord256(permNum)) // already shifted
 	if !ValidPermN(permN) {
 		return nil, ptypes.ErrInvalidPermission(permN)
 	}
-	permInt := byteFromBool(HasPermission(appState, vmAcc, permN))
-	dbg.Printf("snative.hasBasePerm(0x%X, %b) = %v\n", addr.Postfix(20), permN, permInt)
+	hasPermission := HasPermission(state, acc, permN)
+	permInt := byteFromBool(hasPermission)
+	logger.Trace("function", "hasBase", "address", address.String(),
+		"perm_flag", fmt.Sprintf("%b", permN), "has_permission", hasPermission)
 	return LeftPadWord256([]byte{permInt}).Bytes(), nil
 }
 
-func setBase(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
-	addr, permNum, permVal := returnThreeArgs(args)
-	vmAcc := appState.GetAccount(addr)
-	if vmAcc == nil {
-		return nil, fmt.Errorf("Unknown account %X", addr)
+func setBase(state acm.StateWriter, caller acm.Account, args []byte, gas *uint64,
+	logger logging_types.InfoTraceLogger) (output []byte, err error) {
+
+	addrWord256, permNum, permVal := returnThreeArgs(args)
+	address := acm.AddressFromWord256(addrWord256)
+	acc, err := acm.GetMutableAccount(state, address)
+	if err != nil {
+		return nil, err
+	}
+	if acc == nil {
+		return nil, fmt.Errorf("unknown account %s", address)
 	}
 	permN := ptypes.PermFlag(Uint64FromWord256(permNum))
 	if !ValidPermN(permN) {
 		return nil, ptypes.ErrInvalidPermission(permN)
 	}
 	permV := !permVal.IsZero()
-	if err = vmAcc.Permissions.Base.Set(permN, permV); err != nil {
+	if err = acc.MutablePermissions().Base.Set(permN, permV); err != nil {
 		return nil, err
 	}
-	appState.UpdateAccount(vmAcc)
-	dbg.Printf("snative.setBasePerm(0x%X, %b, %v)\n", addr.Postfix(20), permN, permV)
-	return effectivePermBytes(vmAcc.Permissions.Base, globalPerms(appState)), nil
+	state.UpdateAccount(acc)
+	logger.Trace("function", "setBase", "address", address.String(),
+		"permission_flag", fmt.Sprintf("%b", permN),
+		"permission_value", permV)
+	return effectivePermBytes(acc.Permissions().Base, globalPerms(state)), nil
 }
 
-func unsetBase(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
-	addr, permNum := returnTwoArgs(args)
-	vmAcc := appState.GetAccount(addr)
-	if vmAcc == nil {
-		return nil, fmt.Errorf("Unknown account %X", addr)
+func unsetBase(state acm.StateWriter, caller acm.Account, args []byte, gas *uint64,
+	logger logging_types.InfoTraceLogger) (output []byte, err error) {
+
+	addrWord256, permNum := returnTwoArgs(args)
+	address := acm.AddressFromWord256(addrWord256)
+	acc, err := acm.GetMutableAccount(state, address)
+	if err != nil {
+		return nil, err
+	}
+	if acc == nil {
+		return nil, fmt.Errorf("unknown account %s", address)
 	}
 	permN := ptypes.PermFlag(Uint64FromWord256(permNum))
 	if !ValidPermN(permN) {
 		return nil, ptypes.ErrInvalidPermission(permN)
 	}
-	if err = vmAcc.Permissions.Base.Unset(permN); err != nil {
+	if err = acc.MutablePermissions().Base.Unset(permN); err != nil {
 		return nil, err
 	}
-	appState.UpdateAccount(vmAcc)
-	dbg.Printf("snative.unsetBasePerm(0x%X, %b)\n", addr.Postfix(20), permN)
-	return effectivePermBytes(vmAcc.Permissions.Base, globalPerms(appState)), nil
+	state.UpdateAccount(acc)
+	logger.Trace("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
 }
 
-func setGlobal(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
+func setGlobal(state acm.StateWriter, caller acm.Account, args []byte, gas *uint64,
+	logger logging_types.InfoTraceLogger) (output []byte, err error) {
+
 	permNum, permVal := returnTwoArgs(args)
-	vmAcc := appState.GetAccount(ptypes.GlobalPermissionsAddress256)
-	if vmAcc == nil {
-		sanity.PanicSanity("cant find the global permissions account")
+	acc, err := acm.GetMutableAccount(state, permission.GlobalPermissionsAddress)
+	if err != nil {
+		return nil, err
+	}
+	if acc == nil {
+		panic("cant find the global permissions account")
 	}
 	permN := ptypes.PermFlag(Uint64FromWord256(permNum))
 	if !ValidPermN(permN) {
 		return nil, ptypes.ErrInvalidPermission(permN)
 	}
 	permV := !permVal.IsZero()
-	if err = vmAcc.Permissions.Base.Set(permN, permV); err != nil {
+	if err = acc.MutablePermissions().Base.Set(permN, permV); err != nil {
 		return nil, err
 	}
-	appState.UpdateAccount(vmAcc)
-	dbg.Printf("snative.setGlobalPerm(%b, %v)\n", permN, permV)
-	return permBytes(vmAcc.Permissions.Base.ResultantPerms()), nil
+	state.UpdateAccount(acc)
+	logger.Trace("function", "setGlobal",
+		"permission_flag", fmt.Sprintf("%b", permN),
+		"permission_value", permV)
+	return permBytes(acc.Permissions().Base.ResultantPerms()), nil
 }
 
-func hasRole(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
-	addr, role := returnTwoArgs(args)
-	vmAcc := appState.GetAccount(addr)
-	if vmAcc == nil {
-		return nil, fmt.Errorf("Unknown account %X", addr)
+func hasRole(state acm.StateWriter, caller acm.Account, args []byte, gas *uint64,
+	logger logging_types.InfoTraceLogger) (output []byte, err error) {
+
+	addrWord256, role := returnTwoArgs(args)
+	address := acm.AddressFromWord256(addrWord256)
+	acc, err := state.GetAccount(address)
+	if err != nil {
+		return nil, err
+	}
+	if acc == nil {
+		return nil, fmt.Errorf("unknown account %s", address)
 	}
 	roleS := string(role.Bytes())
-	permInt := byteFromBool(vmAcc.Permissions.HasRole(roleS))
-	dbg.Printf("snative.hasRole(0x%X, %s) = %v\n", addr.Postfix(20), roleS, permInt > 0)
+	hasRole := acc.Permissions().HasRole(roleS)
+	permInt := byteFromBool(hasRole)
+	logger.Trace("function", "hasRole", "address", address.String(),
+		"role", roleS,
+		"has_role", hasRole)
 	return LeftPadWord256([]byte{permInt}).Bytes(), nil
 }
 
-func addRole(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
-	addr, role := returnTwoArgs(args)
-	vmAcc := appState.GetAccount(addr)
-	if vmAcc == nil {
-		return nil, fmt.Errorf("Unknown account %X", addr)
+func addRole(state acm.StateWriter, caller acm.Account, args []byte, gas *uint64,
+	logger logging_types.InfoTraceLogger) (output []byte, err error) {
+
+	addrWord256, role := returnTwoArgs(args)
+	address := acm.AddressFromWord256(addrWord256)
+	acc, err := acm.GetMutableAccount(state, address)
+	if err != nil {
+		return nil, err
+	}
+	if acc == nil {
+		return nil, fmt.Errorf("unknown account %s", address)
 	}
 	roleS := string(role.Bytes())
-	permInt := byteFromBool(vmAcc.Permissions.AddRole(roleS))
-	appState.UpdateAccount(vmAcc)
-	dbg.Printf("snative.addRole(0x%X, %s) = %v\n", addr.Postfix(20), roleS, permInt > 0)
+	roleAdded := acc.MutablePermissions().AddRole(roleS)
+	permInt := byteFromBool(roleAdded)
+	state.UpdateAccount(acc)
+	logger.Trace("function", "addRole", "address", address.String(),
+		"role", roleS,
+		"role_added", roleAdded)
 	return LeftPadWord256([]byte{permInt}).Bytes(), nil
 }
 
-func removeRole(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
-	addr, role := returnTwoArgs(args)
-	vmAcc := appState.GetAccount(addr)
-	if vmAcc == nil {
-		return nil, fmt.Errorf("Unknown account %X", addr)
+func removeRole(state acm.StateWriter, caller acm.Account, args []byte, gas *uint64,
+	logger logging_types.InfoTraceLogger) (output []byte, err error) {
+
+	addrWord256, role := returnTwoArgs(args)
+	address := acm.AddressFromWord256(addrWord256)
+	acc, err := acm.GetMutableAccount(state, address)
+	if err != nil {
+		return nil, err
+	}
+	if acc == nil {
+		return nil, fmt.Errorf("unknown account %s", address)
 	}
 	roleS := string(role.Bytes())
-	permInt := byteFromBool(vmAcc.Permissions.RmRole(roleS))
-	appState.UpdateAccount(vmAcc)
-	dbg.Printf("snative.rmRole(0x%X, %s) = %v\n", addr.Postfix(20), roleS, permInt > 0)
+	roleRemoved := acc.MutablePermissions().RmRole(roleS)
+	permInt := byteFromBool(roleRemoved)
+	state.UpdateAccount(acc)
+	logger.Trace("function", "removeRole", "address", address.String(),
+		"role", roleS,
+		"role_removed", roleRemoved)
 	return LeftPadWord256([]byte{permInt}).Bytes(), nil
 }
 
 //------------------------------------------------------------------------------------------------
 // Errors and utility funcs
 
-type ErrInvalidPermission struct {
-	Address Word256
+type ErrLacksSNativePermission struct {
+	Address acm.Address
 	SNative string
 }
 
-func (e ErrInvalidPermission) Error() string {
-	return fmt.Sprintf("Account %X does not have permission snative.%s", e.Address.Postfix(20), e.SNative)
+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 <= ptypes.TopPermFlag
+	return n <= permission.TopPermFlag
 }
 
 // Get the global BasePermissions
-func globalPerms(appState AppState) ptypes.BasePermissions {
-	vmAcc := appState.GetAccount(ptypes.GlobalPermissionsAddress256)
-	if vmAcc == nil {
-		sanity.PanicSanity("cant find the global permissions account")
-	}
-	return vmAcc.Permissions.Base
+func globalPerms(state acm.StateWriter) ptypes.BasePermissions {
+	return permission.GlobalAccountPermissions(state).Base
 }
 
-// Compute the effective permissions from an Account's BasePermissions by
+// Compute the effective permissions from an acm.Account's BasePermissions by
 // taking the bitwise or with the global BasePermissions resultant permissions
 func effectivePermBytes(basePerms ptypes.BasePermissions,
 	globalPerms ptypes.BasePermissions) []byte {
diff --git a/manager/burrow-mint/evm/snative_test.go b/execution/evm/snative_test.go
similarity index 76%
rename from manager/burrow-mint/evm/snative_test.go
rename to execution/evm/snative_test.go
index 18006ad6..ab173b97 100644
--- a/manager/burrow-mint/evm/snative_test.go
+++ b/execution/evm/snative_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package vm
+package evm
 
 import (
 	"encoding/hex"
@@ -20,11 +20,13 @@ import (
 
 	"strings"
 
-	"github.com/hyperledger/burrow/manager/burrow-mint/evm/abi"
-	. "github.com/hyperledger/burrow/manager/burrow-mint/evm/opcodes"
-	"github.com/hyperledger/burrow/manager/burrow-mint/evm/sha3"
+	acm "github.com/hyperledger/burrow/account"
+	. "github.com/hyperledger/burrow/binary"
+	"github.com/hyperledger/burrow/execution/evm/abi"
+	"github.com/hyperledger/burrow/execution/evm/asm/bc"
+	"github.com/hyperledger/burrow/execution/evm/sha3"
+	"github.com/hyperledger/burrow/permission"
 	ptypes "github.com/hyperledger/burrow/permission/types"
-	. "github.com/hyperledger/burrow/word256"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -63,12 +65,12 @@ func TestPermissionsContractSignatures(t *testing.T) {
 func TestSNativeContractDescription_Dispatch(t *testing.T) {
 	contract := SNativeContracts()["Permissions"]
 	state := newAppState()
-	caller := &Account{
-		Address: addr(1, 1, 1),
-	}
-	grantee := &Account{
-		Address: addr(2, 2, 2),
-	}
+	caller := acm.ConcreteAccount{
+		Address: acm.Address{1, 1, 1},
+	}.MutableAccount()
+	grantee := acm.ConcreteAccount{
+		Address: acm.Address{2, 2, 2},
+	}.MutableAccount()
 	state.UpdateAccount(grantee)
 
 	function, err := contract.FunctionByName("addRole")
@@ -76,20 +78,20 @@ func TestSNativeContractDescription_Dispatch(t *testing.T) {
 		t.Fatalf("Could not get function: %s", err)
 	}
 	funcID := function.ID()
-	gas := int64(1000)
+	gas := uint64(1000)
 
 	// Should fail since we have no permissions
-	retValue, err := contract.Dispatch(state, caller, Bytecode(funcID[:],
-		grantee.Address, permFlagToWord256(ptypes.CreateAccount)), &gas)
-	assert.Error(t, err)
-	if err != nil {
-		assert.Contains(t, err.Error(), "does not have permission")
+	retValue, err := contract.Dispatch(state, caller, bc.Splice(funcID[:],
+		grantee.Address(), permFlagToWord256(permission.CreateAccount)), &gas, logger)
+	if !assert.Error(t, err, "Should fail due to lack of permissions") {
+		return
 	}
+	assert.IsType(t, err, ErrLacksSNativePermission{})
 
 	// Grant all permissions and dispatch should success
-	caller.Permissions = allAccountPermissions()
-	retValue, err = contract.Dispatch(state, caller, Bytecode(funcID[:],
-		grantee.Address, permFlagToWord256(ptypes.CreateAccount)), &gas)
+	caller.SetPermissions(allAccountPermissions())
+	retValue, err = contract.Dispatch(state, caller, bc.Splice(funcID[:],
+		grantee.Address().Word256(), permFlagToWord256(permission.CreateAccount)), &gas, logger)
 	assert.NoError(t, err)
 	assert.Equal(t, retValue, LeftPadBytes([]byte{1}, 32))
 }
@@ -97,7 +99,7 @@ func TestSNativeContractDescription_Dispatch(t *testing.T) {
 func TestSNativeContractDescription_Address(t *testing.T) {
 	contract := NewSNativeContract("A comment",
 		"CoolButVeryLongNamedContractOfDoom")
-	assert.Equal(t, sha3.Sha3(([]byte)(contract.Name))[12:], contract.AddressBytes())
+	assert.Equal(t, sha3.Sha3(([]byte)(contract.Name))[12:], contract.Address().Bytes())
 }
 
 //
@@ -105,7 +107,8 @@ func TestSNativeContractDescription_Address(t *testing.T) {
 //
 func assertFunctionIDSignature(t *testing.T, contract *SNativeContractDescription,
 	funcIDHex string, expectedSignature string) {
-	function, err := contract.FunctionByID(funcIDFromHex(t, funcIDHex))
+	fromHex := funcIDFromHex(t, funcIDHex)
+	function, err := contract.FunctionByID(fromHex)
 	assert.NoError(t, err,
 		"Error retrieving SNativeFunctionDescription with ID %s", funcIDHex)
 	if err == nil {
@@ -127,15 +130,11 @@ func permFlagToWord256(permFlag ptypes.PermFlag) Word256 {
 	return Uint64ToWord256(uint64(permFlag))
 }
 
-func addr(rightBytes ...uint8) Word256 {
-	return LeftPadWord256(rightBytes)
-}
-
 func allAccountPermissions() ptypes.AccountPermissions {
 	return ptypes.AccountPermissions{
 		Base: ptypes.BasePermissions{
-			Perms:  ptypes.AllPermFlags,
-			SetBit: ptypes.AllPermFlags,
+			Perms:  permission.AllPermFlags,
+			SetBit: permission.AllPermFlags,
 		},
 		Roles: []string{},
 	}
diff --git a/manager/burrow-mint/evm/stack.go b/execution/evm/stack.go
similarity index 84%
rename from manager/burrow-mint/evm/stack.go
rename to execution/evm/stack.go
index f9d48986..0d8a8f3f 100644
--- a/manager/burrow-mint/evm/stack.go
+++ b/execution/evm/stack.go
@@ -12,14 +12,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package vm
+package evm
 
 import (
 	"fmt"
 
-	"github.com/hyperledger/burrow/common/math/integral"
-	"github.com/hyperledger/burrow/common/sanity"
-	. "github.com/hyperledger/burrow/word256"
+	. "github.com/hyperledger/burrow/binary"
 )
 
 // Not goroutine safe
@@ -27,11 +25,11 @@ type Stack struct {
 	data []Word256
 	ptr  int
 
-	gas *int64
+	gas *uint64
 	err *error
 }
 
-func NewStack(capacity int, gas *int64, err *error) *Stack {
+func NewStack(capacity int, gas *uint64, err *error) *Stack {
 	return &Stack{
 		data: make([]Word256, capacity),
 		ptr:  0,
@@ -40,7 +38,7 @@ func NewStack(capacity int, gas *int64, err *error) *Stack {
 	}
 }
 
-func (st *Stack) useGas(gasToUse int64) {
+func (st *Stack) useGas(gasToUse uint64) {
 	if *st.gas > gasToUse {
 		*st.gas -= gasToUse
 	} else {
@@ -64,10 +62,10 @@ func (st *Stack) Push(d Word256) {
 	st.ptr++
 }
 
-// currently only called after Sha3
+// currently only called after sha3.Sha3
 func (st *Stack) PushBytes(bz []byte) {
 	if len(bz) != 32 {
-		sanity.PanicSanity("Invalid bytes size: expected 32")
+		panic("Invalid bytes size: expected 32")
 	}
 	st.Push(LeftPadWord256(bz))
 }
@@ -76,6 +74,10 @@ func (st *Stack) Push64(i int64) {
 	st.Push(Int64ToWord256(i))
 }
 
+func (st *Stack) PushU64(i uint64) {
+	st.Push(Uint64ToWord256(i))
+}
+
 func (st *Stack) Pop() Word256 {
 	st.useGas(GasStackOp)
 	if st.ptr == 0 {
@@ -95,6 +97,11 @@ func (st *Stack) Pop64() int64 {
 	return Int64FromWord256(d)
 }
 
+func (st *Stack) PopU64() uint64 {
+	d := st.Pop()
+	return Uint64FromWord256(d)
+}
+
 func (st *Stack) Len() int {
 	return st.ptr
 }
@@ -129,7 +136,10 @@ func (st *Stack) Peek() Word256 {
 func (st *Stack) Print(n int) {
 	fmt.Println("### stack ###")
 	if st.ptr > 0 {
-		nn := integral.MinInt(n, st.ptr)
+		nn := n
+		if st.ptr < n {
+			nn = st.ptr
+		}
 		for j, i := 0, st.ptr-1; i > st.ptr-1-nn; i-- {
 			fmt.Printf("%-3d  %X\n", j, st.data[i])
 			j += 1
diff --git a/manager/burrow-mint/evm/vm.go b/execution/evm/vm.go
similarity index 67%
rename from manager/burrow-mint/evm/vm.go
rename to execution/evm/vm.go
index 60ae0f64..2813a5e5 100644
--- a/manager/burrow-mint/evm/vm.go
+++ b/execution/evm/vm.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package vm
+package evm
 
 import (
 	"bytes"
@@ -20,14 +20,17 @@ import (
 	"fmt"
 	"math/big"
 
-	"github.com/hyperledger/burrow/common/sanity"
-	. "github.com/hyperledger/burrow/manager/burrow-mint/evm/opcodes"
-	"github.com/hyperledger/burrow/manager/burrow-mint/evm/sha3"
+	acm "github.com/hyperledger/burrow/account"
+	. "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"
+	"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"
-	. "github.com/hyperledger/burrow/word256"
-
-	"github.com/tendermint/go-events"
 )
 
 var (
@@ -59,46 +62,43 @@ const (
 	callStackCapacity = 100 // TODO ensure usage.
 )
 
-type Debug bool
-
-var dbg Debug
-
-func SetDebug(d bool) {
-	dbg = Debug(d)
-}
-
-func (d Debug) Printf(s string, a ...interface{}) {
-	if d {
-		fmt.Printf(s, a...)
-	}
+type Params struct {
+	BlockHeight uint64
+	BlockHash   Word256
+	BlockTime   int64
+	GasLimit    uint64
 }
 
 type VM struct {
-	appState       AppState
+	state          acm.StateWriter
 	memoryProvider func() Memory
 	params         Params
-	origin         Word256
+	origin         acm.Address
 	txid           []byte
-
-	callDepth int
-
-	evc events.Fireable
+	callDepth      int
+	evc            event.Fireable
+	logger         logging_types.InfoTraceLogger
 }
 
-func NewVM(appState AppState, memoryProvider func() Memory, params Params,
-	origin Word256, txid []byte) *VM {
+func NewVM(state acm.StateWriter, memoryProvider func() Memory, params Params, origin acm.Address, txid []byte,
+	logger logging_types.InfoTraceLogger) *VM {
 	return &VM{
-		appState:       appState,
+		state:          state,
 		memoryProvider: memoryProvider,
 		params:         params,
 		origin:         origin,
 		callDepth:      0,
 		txid:           txid,
+		logger:         logger.WithPrefix(structure.ComponentKey, "EVM"),
 	}
 }
 
-// satisfies events.Eventable
-func (vm *VM) SetFireable(evc events.Fireable) {
+func (vm *VM) Debugf(format string, a ...interface{}) {
+	logging.TraceMsg(vm.logger, fmt.Sprintf(format, a...))
+}
+
+// satisfies go_events.Eventable
+func (vm *VM) SetFireable(evc event.Fireable) {
 	vm.evc = evc
 }
 
@@ -108,24 +108,25 @@ func (vm *VM) SetFireable(evc events.Fireable) {
 // 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(appState AppState, acc *Account, perm ptypes.PermFlag) bool {
-	v, err := acc.Permissions.Base.Get(perm)
+func HasPermission(state acm.StateWriter, acc acm.Account, perm ptypes.PermFlag) bool {
+	v, err := acc.Permissions().Base.Get(perm)
 	if _, ok := err.(ptypes.ErrValueNotSet); ok {
-		if appState == nil {
+		if state == nil {
 			// In this case the permission is unknown
 			return false
 		}
-		return HasPermission(nil, appState.GetAccount(ptypes.GlobalPermissionsAddress256), perm)
+		return HasPermission(nil, permission.GlobalPermissionsAccount(state), perm)
 	}
 	return v
 }
 
-func (vm *VM) fireCallEvent(exception *string, output *[]byte, caller, callee *Account, input []byte, value int64, gas *int64) {
+func (vm *VM) fireCallEvent(exception *string, output *[]byte, callerAddress, calleeAddress acm.Address, input []byte, value uint64, gas *uint64) {
 	// fire the post call event (including exception if applicable)
 	if vm.evc != nil {
-		vm.evc.FireEvent(txs.EventStringAccCall(callee.Address.Postfix(20)), txs.EventDataCall{
-			&txs.CallData{caller.Address.Postfix(20), callee.Address.Postfix(20), input, value, *gas},
-			vm.origin.Postfix(20),
+		stringAccCall := events.EventStringAccCall(calleeAddress)
+		vm.evc.Fire(stringAccCall, events.EventDataCall{
+			&events.CallData{Caller: callerAddress, Callee: calleeAddress, Data: input, Value: value, Gas: *gas},
+			vm.origin,
 			vm.txid,
 			*output,
 			*exception,
@@ -133,17 +134,17 @@ func (vm *VM) fireCallEvent(exception *string, output *[]byte, caller, callee *A
 	}
 }
 
-// CONTRACT appState is aware of caller and callee, so we can just mutate them.
+// CONTRACT state is aware of caller and callee, so we can just mutate them.
 // CONTRACT code and input are not mutated.
 // CONTRACT returned 'ret' is a new compact slice.
 // value: To be transferred from caller to callee. Refunded upon error.
 // gas:   Available gas. No refunds for gas.
 // code: May be nil, since the CALL opcode may be used to send value from contracts to accounts
-func (vm *VM) Call(caller, callee *Account, code, input []byte, value int64, gas *int64) (output []byte, err error) {
+func (vm *VM) Call(caller, 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)
-	defer vm.fireCallEvent(exception, &output, caller, callee, input, value, gas)
+	defer vm.fireCallEvent(exception, &output, caller.Address(), callee.Address(), input, value, gas)
 
 	if err = transfer(caller, callee, value); err != nil {
 		*exception = err.Error()
@@ -159,7 +160,7 @@ func (vm *VM) Call(caller, callee *Account, code, input []byte, value int64, gas
 			err := transfer(callee, caller, value)
 			if err != nil {
 				// data has been corrupted in ram
-				sanity.PanicCrisis("Could not return value to caller")
+				panic("Could not return value to caller")
 			}
 		}
 	}
@@ -171,12 +172,12 @@ func (vm *VM) Call(caller, callee *Account, code, input []byte, value int64, gas
 // 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 *Account, code, input []byte, value int64, gas *int64) (output []byte, err error) {
+func (vm *VM) DelegateCall(caller, 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)
 	// NOTE: [ben] hotfix for issue 371;
-	// introduce event EventStringAccDelegateCall Acc/%X/DelegateCall
+	// introduce event EventStringAccDelegateCall Acc/%s/DelegateCall
 	// defer vm.fireCallEvent(exception, &output, caller, callee, input, value, gas)
 
 	// DelegateCall does not transfer the value to the callee.
@@ -195,7 +196,7 @@ func (vm *VM) DelegateCall(caller, callee *Account, code, input []byte, value in
 
 // Try to deduct gasToUse from gasLeft.  If ok return false, otherwise
 // set err and return true.
-func useGasNegative(gasLeft *int64, gasToUse int64, err *error) bool {
+func useGasNegative(gasLeft *uint64, gasToUse uint64, err *error) bool {
 	if *gasLeft >= gasToUse {
 		*gasLeft -= gasToUse
 		return false
@@ -206,8 +207,9 @@ func useGasNegative(gasLeft *int64, gasToUse int64, err *error) bool {
 }
 
 // Just like Call() but does not transfer 'value' or modify the callDepth.
-func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas *int64) (output []byte, err error) {
-	dbg.Printf("(%d) (%X) %X (code=%d) gas: %v (d) %X\n", vm.callDepth, caller.Address[:4], callee.Address, len(callee.Code), *gas, input)
+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(),
+		len(callee.Code()), *gas, input)
 
 	var (
 		pc     int64 = 0
@@ -222,7 +224,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 		}
 
 		var op = codeGetOp(code, pc)
-		dbg.Printf("(pc) %-3d (op) %-14s (st) %-4d ", pc, op.String(), stack.Len())
+		vm.Debugf("(pc) %-3d (op) %-14s (st) %-4d ", pc, op.String(), stack.Len())
 
 		switch op {
 
@@ -233,7 +235,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			sum := new(big.Int).Add(xb, yb)
 			res := LeftPadWord256(U256(sum).Bytes())
 			stack.Push(res)
-			dbg.Printf(" %v + %v = %v (%X)\n", xb, yb, sum, res)
+			vm.Debugf(" %v + %v = %v (%X)\n", xb, yb, sum, res)
 
 		case MUL: // 0x02
 			x, y := stack.Pop(), stack.Pop()
@@ -242,7 +244,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			prod := new(big.Int).Mul(xb, yb)
 			res := LeftPadWord256(U256(prod).Bytes())
 			stack.Push(res)
-			dbg.Printf(" %v * %v = %v (%X)\n", xb, yb, prod, res)
+			vm.Debugf(" %v * %v = %v (%X)\n", xb, yb, prod, res)
 
 		case SUB: // 0x03
 			x, y := stack.Pop(), stack.Pop()
@@ -251,69 +253,69 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			diff := new(big.Int).Sub(xb, yb)
 			res := LeftPadWord256(U256(diff).Bytes())
 			stack.Push(res)
-			dbg.Printf(" %v - %v = %v (%X)\n", xb, yb, diff, res)
+			vm.Debugf(" %v - %v = %v (%X)\n", xb, yb, diff, res)
 
 		case DIV: // 0x04
 			x, y := stack.Pop(), stack.Pop()
 			if y.IsZero() {
 				stack.Push(Zero256)
-				dbg.Printf(" %x / %x = %v\n", x, y, 0)
+				vm.Debugf(" %x / %x = %v\n", x, y, 0)
 			} else {
 				xb := new(big.Int).SetBytes(x[:])
 				yb := new(big.Int).SetBytes(y[:])
 				div := new(big.Int).Div(xb, yb)
 				res := LeftPadWord256(U256(div).Bytes())
 				stack.Push(res)
-				dbg.Printf(" %v / %v = %v (%X)\n", xb, yb, div, res)
+				vm.Debugf(" %v / %v = %v (%X)\n", xb, yb, div, res)
 			}
 
 		case SDIV: // 0x05
 			x, y := stack.Pop(), stack.Pop()
 			if y.IsZero() {
 				stack.Push(Zero256)
-				dbg.Printf(" %x / %x = %v\n", x, y, 0)
+				vm.Debugf(" %x / %x = %v\n", x, y, 0)
 			} else {
 				xb := S256(new(big.Int).SetBytes(x[:]))
 				yb := S256(new(big.Int).SetBytes(y[:]))
 				div := new(big.Int).Div(xb, yb)
 				res := LeftPadWord256(U256(div).Bytes())
 				stack.Push(res)
-				dbg.Printf(" %v / %v = %v (%X)\n", xb, yb, div, res)
+				vm.Debugf(" %v / %v = %v (%X)\n", xb, yb, div, res)
 			}
 
 		case MOD: // 0x06
 			x, y := stack.Pop(), stack.Pop()
 			if y.IsZero() {
 				stack.Push(Zero256)
-				dbg.Printf(" %v %% %v = %v\n", x, y, 0)
+				vm.Debugf(" %v %% %v = %v\n", x, y, 0)
 			} else {
 				xb := new(big.Int).SetBytes(x[:])
 				yb := new(big.Int).SetBytes(y[:])
 				mod := new(big.Int).Mod(xb, yb)
 				res := LeftPadWord256(U256(mod).Bytes())
 				stack.Push(res)
-				dbg.Printf(" %v %% %v = %v (%X)\n", xb, yb, mod, res)
+				vm.Debugf(" %v %% %v = %v (%X)\n", xb, yb, mod, res)
 			}
 
 		case SMOD: // 0x07
 			x, y := stack.Pop(), stack.Pop()
 			if y.IsZero() {
 				stack.Push(Zero256)
-				dbg.Printf(" %v %% %v = %v\n", x, y, 0)
+				vm.Debugf(" %v %% %v = %v\n", x, y, 0)
 			} else {
 				xb := S256(new(big.Int).SetBytes(x[:]))
 				yb := S256(new(big.Int).SetBytes(y[:]))
 				mod := new(big.Int).Mod(xb, yb)
 				res := LeftPadWord256(U256(mod).Bytes())
 				stack.Push(res)
-				dbg.Printf(" %v %% %v = %v (%X)\n", xb, yb, mod, res)
+				vm.Debugf(" %v %% %v = %v (%X)\n", xb, yb, mod, res)
 			}
 
 		case ADDMOD: // 0x08
 			x, y, z := stack.Pop(), stack.Pop(), stack.Pop()
 			if z.IsZero() {
 				stack.Push(Zero256)
-				dbg.Printf(" %v %% %v = %v\n", x, y, 0)
+				vm.Debugf(" %v %% %v = %v\n", x, y, 0)
 			} else {
 				xb := new(big.Int).SetBytes(x[:])
 				yb := new(big.Int).SetBytes(y[:])
@@ -322,7 +324,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 				mod := new(big.Int).Mod(add, zb)
 				res := LeftPadWord256(U256(mod).Bytes())
 				stack.Push(res)
-				dbg.Printf(" %v + %v %% %v = %v (%X)\n",
+				vm.Debugf(" %v + %v %% %v = %v (%X)\n",
 					xb, yb, zb, mod, res)
 			}
 
@@ -330,7 +332,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			x, y, z := stack.Pop(), stack.Pop(), stack.Pop()
 			if z.IsZero() {
 				stack.Push(Zero256)
-				dbg.Printf(" %v %% %v = %v\n", x, y, 0)
+				vm.Debugf(" %v %% %v = %v\n", x, y, 0)
 			} else {
 				xb := new(big.Int).SetBytes(x[:])
 				yb := new(big.Int).SetBytes(y[:])
@@ -339,7 +341,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 				mod := new(big.Int).Mod(mul, zb)
 				res := LeftPadWord256(U256(mod).Bytes())
 				stack.Push(res)
-				dbg.Printf(" %v * %v %% %v = %v (%X)\n",
+				vm.Debugf(" %v * %v %% %v = %v (%X)\n",
 					xb, yb, zb, mod, res)
 			}
 
@@ -350,7 +352,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			pow := new(big.Int).Exp(xb, yb, big.NewInt(0))
 			res := LeftPadWord256(U256(pow).Bytes())
 			stack.Push(res)
-			dbg.Printf(" %v ** %v = %v (%X)\n", xb, yb, pow, res)
+			vm.Debugf(" %v ** %v = %v (%X)\n", xb, yb, pow, res)
 
 		case SIGNEXTEND: // 0x0B
 			back := stack.Pop()
@@ -367,7 +369,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 					numb.Add(numb, mask)
 				}
 				res := LeftPadWord256(U256(numb).Bytes())
-				dbg.Printf(" = %v (%X)", numb, res)
+				vm.Debugf(" = %v (%X)", numb, res)
 				stack.Push(res)
 			}
 
@@ -377,10 +379,10 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			yb := new(big.Int).SetBytes(y[:])
 			if xb.Cmp(yb) < 0 {
 				stack.Push64(1)
-				dbg.Printf(" %v < %v = %v\n", xb, yb, 1)
+				vm.Debugf(" %v < %v = %v\n", xb, yb, 1)
 			} else {
 				stack.Push(Zero256)
-				dbg.Printf(" %v < %v = %v\n", xb, yb, 0)
+				vm.Debugf(" %v < %v = %v\n", xb, yb, 0)
 			}
 
 		case GT: // 0x11
@@ -389,10 +391,10 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			yb := new(big.Int).SetBytes(y[:])
 			if xb.Cmp(yb) > 0 {
 				stack.Push64(1)
-				dbg.Printf(" %v > %v = %v\n", xb, yb, 1)
+				vm.Debugf(" %v > %v = %v\n", xb, yb, 1)
 			} else {
 				stack.Push(Zero256)
-				dbg.Printf(" %v > %v = %v\n", xb, yb, 0)
+				vm.Debugf(" %v > %v = %v\n", xb, yb, 0)
 			}
 
 		case SLT: // 0x12
@@ -401,10 +403,10 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			yb := S256(new(big.Int).SetBytes(y[:]))
 			if xb.Cmp(yb) < 0 {
 				stack.Push64(1)
-				dbg.Printf(" %v < %v = %v\n", xb, yb, 1)
+				vm.Debugf(" %v < %v = %v\n", xb, yb, 1)
 			} else {
 				stack.Push(Zero256)
-				dbg.Printf(" %v < %v = %v\n", xb, yb, 0)
+				vm.Debugf(" %v < %v = %v\n", xb, yb, 0)
 			}
 
 		case SGT: // 0x13
@@ -413,30 +415,30 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			yb := S256(new(big.Int).SetBytes(y[:]))
 			if xb.Cmp(yb) > 0 {
 				stack.Push64(1)
-				dbg.Printf(" %v > %v = %v\n", xb, yb, 1)
+				vm.Debugf(" %v > %v = %v\n", xb, yb, 1)
 			} else {
 				stack.Push(Zero256)
-				dbg.Printf(" %v > %v = %v\n", xb, yb, 0)
+				vm.Debugf(" %v > %v = %v\n", xb, yb, 0)
 			}
 
 		case EQ: // 0x14
 			x, y := stack.Pop(), stack.Pop()
 			if bytes.Equal(x[:], y[:]) {
 				stack.Push64(1)
-				dbg.Printf(" %X == %X = %v\n", x, y, 1)
+				vm.Debugf(" %X == %X = %v\n", x, y, 1)
 			} else {
 				stack.Push(Zero256)
-				dbg.Printf(" %X == %X = %v\n", x, y, 0)
+				vm.Debugf(" %X == %X = %v\n", x, y, 0)
 			}
 
 		case ISZERO: // 0x15
 			x := stack.Pop()
 			if x.IsZero() {
 				stack.Push64(1)
-				dbg.Printf(" %v == 0 = %v\n", x, 1)
+				vm.Debugf(" %v == 0 = %v\n", x, 1)
 			} else {
 				stack.Push(Zero256)
-				dbg.Printf(" %v == 0 = %v\n", x, 0)
+				vm.Debugf(" %v == 0 = %v\n", x, 0)
 			}
 
 		case AND: // 0x16
@@ -446,7 +448,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 				z[i] = x[i] & y[i]
 			}
 			stack.Push(z)
-			dbg.Printf(" %X & %X = %X\n", x, y, z)
+			vm.Debugf(" %X & %X = %X\n", x, y, z)
 
 		case OR: // 0x17
 			x, y := stack.Pop(), stack.Pop()
@@ -455,7 +457,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 				z[i] = x[i] | y[i]
 			}
 			stack.Push(z)
-			dbg.Printf(" %X | %X = %X\n", x, y, z)
+			vm.Debugf(" %X | %X = %X\n", x, y, z)
 
 		case XOR: // 0x18
 			x, y := stack.Pop(), stack.Pop()
@@ -464,7 +466,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 				z[i] = x[i] ^ y[i]
 			}
 			stack.Push(z)
-			dbg.Printf(" %X ^ %X = %X\n", x, y, z)
+			vm.Debugf(" %X ^ %X = %X\n", x, y, z)
 
 		case NOT: // 0x19
 			x := stack.Pop()
@@ -473,7 +475,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 				z[i] = ^x[i]
 			}
 			stack.Push(z)
-			dbg.Printf(" !%X = %X\n", x, z)
+			vm.Debugf(" !%X = %X\n", x, z)
 
 		case BYTE: // 0x1A
 			idx, val := stack.Pop64(), stack.Pop()
@@ -482,7 +484,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 				res = val[idx]
 			}
 			stack.Push64(int64(res))
-			dbg.Printf(" => 0x%X\n", res)
+			vm.Debugf(" => 0x%X\n", res)
 
 		case SHA3: // 0x20
 			if useGasNegative(gas, GasSha3, &err) {
@@ -491,41 +493,44 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			offset, size := stack.Pop64(), stack.Pop64()
 			data, memErr := memory.Read(offset, size)
 			if memErr != nil {
-				dbg.Printf(" => Memory err: %s", memErr)
+				vm.Debugf(" => Memory err: %s", memErr)
 				return nil, firstErr(err, ErrMemoryOutOfBounds)
 			}
 			data = sha3.Sha3(data)
 			stack.PushBytes(data)
-			dbg.Printf(" => (%v) %X\n", size, data)
+			vm.Debugf(" => (%v) %X\n", size, data)
 
 		case ADDRESS: // 0x30
-			stack.Push(callee.Address)
-			dbg.Printf(" => %X\n", callee.Address)
+			stack.Push(callee.Address().Word256())
+			vm.Debugf(" => %X\n", callee.Address())
 
 		case BALANCE: // 0x31
 			addr := stack.Pop()
 			if useGasNegative(gas, GasGetAccount, &err) {
 				return nil, err
 			}
-			acc := vm.appState.GetAccount(addr)
+			acc, errAcc := vm.state.GetAccount(acm.AddressFromWord256(addr))
+			if errAcc != nil {
+				return nil, firstErr(err, errAcc)
+			}
 			if acc == nil {
 				return nil, firstErr(err, ErrUnknownAddress)
 			}
-			balance := acc.Balance
-			stack.Push64(balance)
-			dbg.Printf(" => %v (%X)\n", balance, addr)
+			balance := acc.Balance()
+			stack.PushU64(balance)
+			vm.Debugf(" => %v (%X)\n", balance, addr)
 
 		case ORIGIN: // 0x32
-			stack.Push(vm.origin)
-			dbg.Printf(" => %X\n", vm.origin)
+			stack.Push(vm.origin.Word256())
+			vm.Debugf(" => %X\n", vm.origin)
 
 		case CALLER: // 0x33
-			stack.Push(caller.Address)
-			dbg.Printf(" => %X\n", caller.Address)
+			stack.Push(caller.Address().Word256())
+			vm.Debugf(" => %X\n", caller.Address())
 
 		case CALLVALUE: // 0x34
-			stack.Push64(value)
-			dbg.Printf(" => %v\n", value)
+			stack.PushU64(value)
+			vm.Debugf(" => %v\n", value)
 
 		case CALLDATALOAD: // 0x35
 			offset := stack.Pop64()
@@ -535,11 +540,11 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			}
 			res := LeftPadWord256(data)
 			stack.Push(res)
-			dbg.Printf(" => 0x%X\n", res)
+			vm.Debugf(" => 0x%X\n", res)
 
 		case CALLDATASIZE: // 0x36
 			stack.Push64(int64(len(input)))
-			dbg.Printf(" => %d\n", len(input))
+			vm.Debugf(" => %d\n", len(input))
 
 		case CALLDATACOPY: // 0x37
 			memOff := stack.Pop64()
@@ -551,15 +556,15 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			}
 			memErr := memory.Write(memOff, data)
 			if memErr != nil {
-				dbg.Printf(" => Memory err: %s", memErr)
+				vm.Debugf(" => Memory err: %s", memErr)
 				return nil, firstErr(err, ErrMemoryOutOfBounds)
 			}
-			dbg.Printf(" => [%v, %v, %v] %X\n", memOff, inputOff, length, data)
+			vm.Debugf(" => [%v, %v, %v] %X\n", memOff, inputOff, length, data)
 
 		case CODESIZE: // 0x38
 			l := int64(len(code))
 			stack.Push64(l)
-			dbg.Printf(" => %d\n", l)
+			vm.Debugf(" => %d\n", l)
 
 		case CODECOPY: // 0x39
 			memOff := stack.Pop64()
@@ -571,47 +576,53 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			}
 			memErr := memory.Write(memOff, data)
 			if memErr != nil {
-				dbg.Printf(" => Memory err: %s", memErr)
+				vm.Debugf(" => Memory err: %s", memErr)
 				return nil, firstErr(err, ErrMemoryOutOfBounds)
 			}
-			dbg.Printf(" => [%v, %v, %v] %X\n", memOff, codeOff, length, data)
+			vm.Debugf(" => [%v, %v, %v] %X\n", memOff, codeOff, length, data)
 
 		case GASPRICE_DEPRECATED: // 0x3A
 			stack.Push(Zero256)
-			dbg.Printf(" => %X (GASPRICE IS DEPRECATED)\n")
+			vm.Debugf(" => %X (GASPRICE IS DEPRECATED)\n")
 
 		case EXTCODESIZE: // 0x3B
 			addr := stack.Pop()
 			if useGasNegative(gas, GasGetAccount, &err) {
 				return nil, err
 			}
-			acc := vm.appState.GetAccount(addr)
+			acc, errAcc := vm.state.GetAccount(acm.AddressFromWord256(addr))
+			if errAcc != nil {
+				return nil, firstErr(err, errAcc)
+			}
 			if acc == nil {
 				if _, ok := registeredNativeContracts[addr]; !ok {
 					return nil, firstErr(err, ErrUnknownAddress)
 				}
-				dbg.Printf(" => returning code size of 1 to indicated existence of native contract at %X\n", addr)
+				vm.Debugf(" => returning code size of 1 to indicated existence of native contract at %X\n", addr)
 				stack.Push(One256)
 			} else {
-				code := acc.Code
+				code := acc.Code()
 				l := int64(len(code))
 				stack.Push64(l)
-				dbg.Printf(" => %d\n", l)
+				vm.Debugf(" => %d\n", l)
 			}
 		case EXTCODECOPY: // 0x3C
 			addr := stack.Pop()
 			if useGasNegative(gas, GasGetAccount, &err) {
 				return nil, err
 			}
-			acc := vm.appState.GetAccount(addr)
+			acc, errAcc := vm.state.GetAccount(acm.AddressFromWord256(addr))
+			if errAcc != nil {
+				return nil, firstErr(err, errAcc)
+			}
 			if acc == nil {
 				if _, ok := registeredNativeContracts[addr]; ok {
-					dbg.Printf(" => attempted to copy native contract at %X but this is not supported\n", addr)
+					vm.Debugf(" => attempted to copy native contract at %X but this is not supported\n", addr)
 					return nil, firstErr(err, ErrNativeContractCodeCopy)
 				}
 				return nil, firstErr(err, ErrUnknownAddress)
 			}
-			code := acc.Code
+			code := acc.Code()
 			memOff := stack.Pop64()
 			codeOff := stack.Pop64()
 			length := stack.Pop64()
@@ -621,81 +632,84 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			}
 			memErr := memory.Write(memOff, data)
 			if memErr != nil {
-				dbg.Printf(" => Memory err: %s", memErr)
+				vm.Debugf(" => Memory err: %s", memErr)
 				return nil, firstErr(err, ErrMemoryOutOfBounds)
 			}
-			dbg.Printf(" => [%v, %v, %v] %X\n", memOff, codeOff, length, data)
+			vm.Debugf(" => [%v, %v, %v] %X\n", memOff, codeOff, length, data)
 
 		case BLOCKHASH: // 0x40
 			stack.Push(Zero256)
-			dbg.Printf(" => 0x%X (NOT SUPPORTED)\n", stack.Peek().Bytes())
+			vm.Debugf(" => 0x%X (NOT SUPPORTED)\n", stack.Peek().Bytes())
 
 		case COINBASE: // 0x41
 			stack.Push(Zero256)
-			dbg.Printf(" => 0x%X (NOT SUPPORTED)\n", stack.Peek().Bytes())
+			vm.Debugf(" => 0x%X (NOT SUPPORTED)\n", stack.Peek().Bytes())
 
 		case TIMESTAMP: // 0x42
 			time := vm.params.BlockTime
 			stack.Push64(int64(time))
-			dbg.Printf(" => 0x%X\n", time)
+			vm.Debugf(" => 0x%X\n", time)
 
 		case BLOCKHEIGHT: // 0x43
-			number := int64(vm.params.BlockHeight)
-			stack.Push64(number)
-			dbg.Printf(" => 0x%X\n", number)
+			number := vm.params.BlockHeight
+			stack.PushU64(number)
+			vm.Debugf(" => 0x%X\n", number)
 
 		case GASLIMIT: // 0x45
-			stack.Push64(vm.params.GasLimit)
-			dbg.Printf(" => %v\n", vm.params.GasLimit)
+			stack.PushU64(vm.params.GasLimit)
+			vm.Debugf(" => %v\n", vm.params.GasLimit)
 
 		case POP: // 0x50
 			popped := stack.Pop()
-			dbg.Printf(" => 0x%X\n", popped)
+			vm.Debugf(" => 0x%X\n", popped)
 
 		case MLOAD: // 0x51
 			offset := stack.Pop64()
 			data, memErr := memory.Read(offset, 32)
 			if memErr != nil {
-				dbg.Printf(" => Memory err: %s", memErr)
+				vm.Debugf(" => Memory err: %s", memErr)
 				return nil, firstErr(err, ErrMemoryOutOfBounds)
 			}
 			stack.Push(LeftPadWord256(data))
-			dbg.Printf(" => 0x%X @ 0x%X\n", data, offset)
+			vm.Debugf(" => 0x%X @ 0x%X\n", data, offset)
 
 		case MSTORE: // 0x52
 			offset, data := stack.Pop64(), stack.Pop()
 			memErr := memory.Write(offset, data.Bytes())
 			if memErr != nil {
-				dbg.Printf(" => Memory err: %s", memErr)
+				vm.Debugf(" => Memory err: %s", memErr)
 				return nil, firstErr(err, ErrMemoryOutOfBounds)
 			}
-			dbg.Printf(" => 0x%X @ 0x%X\n", data, offset)
+			vm.Debugf(" => 0x%X @ 0x%X\n", data, offset)
 
 		case MSTORE8: // 0x53
 			offset, val := stack.Pop64(), byte(stack.Pop64()&0xFF)
 			memErr := memory.Write(offset, []byte{val})
 			if memErr != nil {
-				dbg.Printf(" => Memory err: %s", memErr)
+				vm.Debugf(" => Memory err: %s", memErr)
 				return nil, firstErr(err, ErrMemoryOutOfBounds)
 			}
-			dbg.Printf(" => [%v] 0x%X\n", offset, val)
+			vm.Debugf(" => [%v] 0x%X\n", offset, val)
 
 		case SLOAD: // 0x54
 			loc := stack.Pop()
-			data := vm.appState.GetStorage(callee.Address, loc)
+			data, errSto := vm.state.GetStorage(callee.Address(), loc)
+			if errSto != nil {
+				return nil, firstErr(err, errSto)
+			}
 			stack.Push(data)
-			dbg.Printf(" {0x%X : 0x%X}\n", loc, data)
+			vm.Debugf(" {0x%X : 0x%X}\n", loc, data)
 
 		case SSTORE: // 0x55
 			loc, data := stack.Pop(), stack.Pop()
 			if useGasNegative(gas, GasStorageUpdate, &err) {
 				return nil, err
 			}
-			vm.appState.SetStorage(callee.Address, loc, data)
-			dbg.Printf(" {0x%X : 0x%X}\n", loc, data)
+			vm.state.SetStorage(callee.Address(), loc, data)
+			vm.Debugf(" {0x%X : 0x%X}\n", loc, data)
 
 		case JUMP: // 0x56
-			if err = jump(code, stack.Pop64(), &pc); err != nil {
+			if err = vm.jump(code, stack.Pop64(), &pc); err != nil {
 				return nil, err
 			}
 			continue
@@ -703,12 +717,12 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 		case JUMPI: // 0x57
 			pos, cond := stack.Pop64(), stack.Pop()
 			if !cond.IsZero() {
-				if err = jump(code, pos, &pc); err != nil {
+				if err = vm.jump(code, pos, &pc); err != nil {
 					return nil, err
 				}
 				continue
 			}
-			dbg.Printf(" ~> false\n")
+			vm.Debugf(" ~> false\n")
 
 		case PC: // 0x58
 			stack.Push64(pc)
@@ -719,14 +733,14 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			// this offset.
 			capacity := memory.Capacity()
 			stack.Push64(capacity)
-			dbg.Printf(" => 0x%X\n", capacity)
+			vm.Debugf(" => 0x%X\n", capacity)
 
 		case GAS: // 0x5A
-			stack.Push64(*gas)
-			dbg.Printf(" => %X\n", *gas)
+			stack.PushU64(*gas)
+			vm.Debugf(" => %X\n", *gas)
 
 		case JUMPDEST: // 0x5B
-			dbg.Printf("\n")
+			vm.Debugf("\n")
 			// Do nothing
 
 		case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
@@ -738,18 +752,18 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			res := LeftPadWord256(codeSegment)
 			stack.Push(res)
 			pc += a
-			dbg.Printf(" => 0x%X\n", res)
+			vm.Debugf(" => 0x%X\n", res)
 			//stack.Print(10)
 
 		case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
 			n := int(op - DUP1 + 1)
 			stack.Dup(n)
-			dbg.Printf(" => [%d] 0x%X\n", n, stack.Peek().Bytes())
+			vm.Debugf(" => [%d] 0x%X\n", n, stack.Peek().Bytes())
 
 		case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
 			n := int(op - SWAP1 + 2)
 			stack.Swap(n)
-			dbg.Printf(" => [%d] %X\n", n, stack.Peek())
+			vm.Debugf(" => [%d] %X\n", n, stack.Peek())
 			//stack.Print(10)
 
 		case LOG0, LOG1, LOG2, LOG3, LOG4:
@@ -761,41 +775,42 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			}
 			data, memErr := memory.Read(offset, size)
 			if memErr != nil {
-				dbg.Printf(" => Memory err: %s", memErr)
+				vm.Debugf(" => Memory err: %s", memErr)
 				return nil, firstErr(err, ErrMemoryOutOfBounds)
 			}
 			if vm.evc != nil {
-				eventID := txs.EventStringLogEvent(callee.Address.Postfix(20))
+				eventID := events.EventStringLogEvent(callee.Address())
 				fmt.Printf("eventID: %s\n", eventID)
-				log := txs.EventDataLog{
-					callee.Address,
-					topics,
-					data,
-					vm.params.BlockHeight,
+				log := events.EventDataLog{
+					Address: callee.Address(),
+					Topics:  topics,
+					Data:    data,
+					Height:  vm.params.BlockHeight,
 				}
-				vm.evc.FireEvent(eventID, log)
+				vm.evc.Fire(eventID, log)
 			}
-			dbg.Printf(" => T:%X D:%X\n", topics, data)
+			vm.Debugf(" => T:%X D:%X\n", topics, data)
 
 		case CREATE: // 0xF0
-			if !HasPermission(vm.appState, callee, ptypes.CreateContract) {
+			if !HasPermission(vm.state, callee, permission.CreateContract) {
 				return nil, ErrPermission{"create_contract"}
 			}
-			contractValue := stack.Pop64()
+			contractValue := stack.PopU64()
 			offset, size := stack.Pop64(), stack.Pop64()
 			input, memErr := memory.Read(offset, size)
 			if memErr != nil {
-				dbg.Printf(" => Memory err: %s", memErr)
+				vm.Debugf(" => Memory err: %s", memErr)
 				return nil, firstErr(err, ErrMemoryOutOfBounds)
 			}
 
 			// Check balance
-			if callee.Balance < contractValue {
+			if callee.Balance() < uint64(contractValue) {
 				return nil, firstErr(err, ErrInsufficientBalance)
 			}
 
 			// TODO charge for gas to create account _ the code length * GasCreateByte
-			newAccount := vm.appState.CreateAccount(callee)
+			newAccount := DeriveNewAccount(callee, permission.GlobalAccountPermissions(vm.state))
+			vm.state.UpdateAccount(newAccount)
 
 			// Run the input to get the contract code.
 			// NOTE: no need to copy 'input' as per Call contract.
@@ -803,15 +818,15 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			if err_ != nil {
 				stack.Push(Zero256)
 			} else {
-				newAccount.Code = ret // Set the code (ret need not be copied as per Call contract)
-				stack.Push(newAccount.Address)
+				newAccount.SetCode(ret) // Set the code (ret need not be copied as per Call contract)
+				stack.Push(newAccount.Address().Word256())
 			}
 
 		case CALL, CALLCODE, DELEGATECALL: // 0xF1, 0xF2, 0xF4
-			if !HasPermission(vm.appState, callee, ptypes.Call) {
+			if !HasPermission(vm.state, callee, permission.Call) {
 				return nil, ErrPermission{"call"}
 			}
-			gasLimit := stack.Pop64()
+			gasLimit := stack.PopU64()
 			addr := stack.Pop()
 			// NOTE: for DELEGATECALL value is preserved from the original
 			// caller, as such it is not stored on stack as an argument
@@ -819,16 +834,16 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			// 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.Pop64()
+				value = stack.PopU64()
 			}
 			inOffset, inSize := stack.Pop64(), stack.Pop64()   // inputs
 			retOffset, retSize := stack.Pop64(), stack.Pop64() // outputs
-			dbg.Printf(" => %X\n", addr)
+			vm.Debugf(" => %X\n", addr)
 
 			// Get the arguments from the memory
 			args, memErr := memory.Read(inOffset, inSize)
 			if memErr != nil {
-				dbg.Printf(" => Memory err: %s", memErr)
+				vm.Debugf(" => Memory err: %s", memErr)
 				return nil, firstErr(err, ErrMemoryOutOfBounds)
 			}
 
@@ -845,21 +860,24 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			var err error
 			if nativeContract := registeredNativeContracts[addr]; nativeContract != nil {
 				// Native contract
-				ret, err = nativeContract(vm.appState, callee, args, &gasLimit)
+				ret, err = nativeContract(vm.state, callee, args, &gasLimit, vm.logger)
 
 				// for now we fire the Call event. maybe later we'll fire more particulars
 				var exception string
 				if err != nil {
 					exception = err.Error()
 				}
-				// NOTE: these fire call events and not particular events for eg name reg or permissions
-				vm.fireCallEvent(&exception, &ret, callee, &Account{Address: addr}, args, value, &gasLimit)
+				// NOTE: these fire call go_events and not particular go_events for eg name reg or permissions
+				vm.fireCallEvent(&exception, &ret, callee.Address(), acm.AddressFromWord256(addr), args, value, &gasLimit)
 			} else {
 				// EVM contract
 				if useGasNegative(gas, GasGetAccount, &err) {
 					return nil, err
 				}
-				acc := vm.appState.GetAccount(addr)
+				acc, errAcc := acm.GetMutableAccount(vm.state, acm.AddressFromWord256(addr))
+				if errAcc != nil {
+					return nil, firstErr(err, errAcc)
+				}
 				// since CALL is used also for sending funds,
 				// acc may not exist yet. This is an error for
 				// CALLCODE, but not for CALL, though I don't think
@@ -868,29 +886,29 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 					if acc == nil {
 						return nil, firstErr(err, ErrUnknownAddress)
 					}
-					ret, err = vm.Call(callee, callee, acc.Code, args, value, &gasLimit)
+					ret, err = vm.Call(callee, callee, acc.Code(), args, value, &gasLimit)
 				} else if op == DELEGATECALL {
 					if acc == nil {
 						return nil, firstErr(err, ErrUnknownAddress)
 					}
-					ret, err = vm.DelegateCall(caller, callee, acc.Code, args, value, &gasLimit)
+					ret, err = vm.DelegateCall(caller, callee, acc.Code(), args, value, &gasLimit)
 				} else {
 					// nil account means we're sending funds to a new account
 					if acc == nil {
-						if !HasPermission(vm.appState, caller, ptypes.CreateAccount) {
+						if !HasPermission(vm.state, caller, permission.CreateAccount) {
 							return nil, ErrPermission{"create_account"}
 						}
-						acc = &Account{Address: addr}
+						acc = (&acm.ConcreteAccount{Address: acm.AddressFromWord256(addr)}).MutableAccount()
 					}
 					// add account to the tx cache
-					vm.appState.UpdateAccount(acc)
-					ret, err = vm.Call(callee, acc, acc.Code, args, value, &gasLimit)
+					vm.state.UpdateAccount(acc)
+					ret, err = vm.Call(callee, acc, acc.Code(), args, value, &gasLimit)
 				}
 			}
 
 			// Push result
 			if err != nil {
-				dbg.Printf("error on call: %s\n", err.Error())
+				vm.Debugf("error on call: %s\n", err.Error())
 				stack.Push(Zero256)
 			} else {
 				stack.Push(One256)
@@ -900,7 +918,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 				// defensively pad or truncate the portion of ret to be returned.
 				memErr := memory.Write(retOffset, RightPadBytes(ret, int(retSize)))
 				if memErr != nil {
-					dbg.Printf(" => Memory err: %s", memErr)
+					vm.Debugf(" => Memory err: %s", memErr)
 					return nil, firstErr(err, ErrMemoryOutOfBounds)
 				}
 			}
@@ -908,16 +926,16 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			// Handle remaining gas.
 			*gas += gasLimit
 
-			dbg.Printf("resume %X (%v)\n", callee.Address, gas)
+			vm.Debugf("resume %s (%v)\n", callee.Address(), gas)
 
 		case RETURN: // 0xF3
 			offset, size := stack.Pop64(), stack.Pop64()
 			output, memErr := memory.Read(offset, size)
 			if memErr != nil {
-				dbg.Printf(" => Memory err: %s", memErr)
+				vm.Debugf(" => Memory err: %s", memErr)
 				return nil, firstErr(err, ErrMemoryOutOfBounds)
 			}
-			dbg.Printf(" => [%v, %v] (%d) 0x%X\n", offset, size, len(output), output)
+			vm.Debugf(" => [%v, %v] (%d) 0x%X\n", offset, size, len(output), output)
 			return output, nil
 
 		case SELFDESTRUCT: // 0xFF
@@ -927,22 +945,25 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			}
 			// TODO if the receiver is , then make it the fee. (?)
 			// TODO: create account if doesn't exist (no reason not to)
-			receiver := vm.appState.GetAccount(addr)
+			receiver, errAcc := acm.GetMutableAccount(vm.state, acm.AddressFromWord256(addr))
+			if errAcc != nil {
+				return nil, firstErr(err, errAcc)
+			}
 			if receiver == nil {
 				return nil, firstErr(err, ErrUnknownAddress)
 			}
-			balance := callee.Balance
-			receiver.Balance += balance
-			vm.appState.UpdateAccount(receiver)
-			vm.appState.RemoveAccount(callee)
-			dbg.Printf(" => (%X) %v\n", addr[:4], balance)
+
+			receiver.AddToBalance(callee.Balance())
+			vm.state.UpdateAccount(receiver)
+			vm.state.RemoveAccount(callee.Address())
+			vm.Debugf(" => (%X) %v\n", addr[:4], callee.Balance())
 			fallthrough
 
 		case STOP: // 0x00
 			return nil, nil
 
 		default:
-			dbg.Printf("(pc) %-3v Invalid opcode %X\n", pc, op)
+			vm.Debugf("(pc) %-3v Invalid opcode %X\n", pc, op)
 			return nil, fmt.Errorf("Invalid opcode %X", op)
 		}
 
@@ -981,13 +1002,13 @@ func codeGetOp(code []byte, n int64) OpCode {
 	}
 }
 
-func jump(code []byte, to int64, pc *int64) (err error) {
+func (vm *VM) jump(code []byte, to int64, pc *int64) (err error) {
 	dest := codeGetOp(code, to)
 	if dest != JUMPDEST {
-		dbg.Printf(" ~> %v invalid jump dest %v\n", to, dest)
+		vm.Debugf(" ~> %v invalid jump dest %v\n", to, dest)
 		return ErrInvalidJumpDest
 	}
-	dbg.Printf(" ~> %v\n", to)
+	vm.Debugf(" ~> %v\n", to)
 	*pc = to
 	return nil
 }
@@ -1000,12 +1021,12 @@ func firstErr(errA, errB error) error {
 	}
 }
 
-func transfer(from, to *Account, amount int64) error {
-	if from.Balance < amount {
+func transfer(from, to acm.MutableAccount, amount uint64) error {
+	if from.Balance() < amount {
 		return ErrInsufficientBalance
 	} else {
-		from.Balance -= amount
-		to.Balance += amount
+		from.SubtractFromBalance(amount)
+		to.AddToBalance(amount)
 		return nil
 	}
 }
diff --git a/manager/burrow-mint/evm/vm_test.go b/execution/evm/vm_test.go
similarity index 65%
rename from manager/burrow-mint/evm/vm_test.go
rename to execution/evm/vm_test.go
index 0dd35682..523ed41d 100644
--- a/manager/burrow-mint/evm/vm_test.go
+++ b/execution/evm/vm_test.go
@@ -12,39 +12,42 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package vm
+package evm
 
 import (
-	"crypto/rand"
 	"encoding/hex"
 	"fmt"
 	"strings"
 	"testing"
 	"time"
 
+	acm "github.com/hyperledger/burrow/account"
+
 	"errors"
 
-	. "github.com/hyperledger/burrow/manager/burrow-mint/evm/opcodes"
-	ptypes "github.com/hyperledger/burrow/permission/types"
-	"github.com/hyperledger/burrow/txs"
-	. "github.com/hyperledger/burrow/word256"
+	. "github.com/hyperledger/burrow/binary"
+	"github.com/hyperledger/burrow/event"
+	exe_events "github.com/hyperledger/burrow/execution/events"
+	. "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/lifecycle"
+	"github.com/hyperledger/burrow/logging/loggers"
+	"github.com/hyperledger/burrow/permission"
 	"github.com/stretchr/testify/assert"
-	"github.com/tendermint/go-events"
 )
 
-func init() {
-	SetDebug(true)
-}
+var logger, _ = lifecycle.NewStdErrLogger()
 
 func newAppState() *FakeAppState {
 	fas := &FakeAppState{
-		accounts: make(map[string]*Account),
+		accounts: make(map[acm.Address]acm.Account),
 		storage:  make(map[string]Word256),
 	}
 	// For default permissions
-	fas.accounts[ptypes.GlobalPermissionsAddress256.String()] = &Account{
-		Permissions: ptypes.DefaultAccountPermissions,
-	}
+	fas.accounts[permission.GlobalPermissionsAddress] = acm.ConcreteAccount{
+		Permissions: permission.DefaultAccountPermissions,
+	}.Account()
 	return fas
 }
 
@@ -57,25 +60,21 @@ func newParams() Params {
 	}
 }
 
-func makeBytes(n int) []byte {
-	b := make([]byte, n)
-	rand.Read(b)
-	return b
+func newAccount(address ...byte) acm.MutableAccount {
+	return acm.ConcreteAccount{
+		Address: acm.AddressFromWord256(RightPadWord256(address)),
+	}.MutableAccount()
 }
 
 // Runs a basic loop
 func TestVM(t *testing.T) {
-	ourVm := NewVM(newAppState(), DefaultDynamicMemoryProvider, newParams(), Zero256, nil)
+	ourVm := NewVM(newAppState(), DefaultDynamicMemoryProvider, newParams(), acm.ZeroAddress, nil, logger)
 
 	// Create accounts
-	account1 := &Account{
-		Address: Int64ToWord256(100),
-	}
-	account2 := &Account{
-		Address: Int64ToWord256(101),
-	}
+	account1 := newAccount(1)
+	account2 := newAccount(1, 0, 1)
 
-	var gas int64 = 100000
+	var gas uint64 = 100000
 	N := []byte{0x0f, 0x0f}
 	// Loop N times
 	code := []byte{0x60, 0x00, 0x60, 0x20, 0x52, 0x5B, byte(0x60 + len(N) - 1)}
@@ -91,17 +90,13 @@ func TestVM(t *testing.T) {
 }
 
 func TestJumpErr(t *testing.T) {
-	ourVm := NewVM(newAppState(), DefaultDynamicMemoryProvider, newParams(), Zero256, nil)
+	ourVm := NewVM(newAppState(), DefaultDynamicMemoryProvider, newParams(), acm.ZeroAddress, nil, logger)
 
 	// Create accounts
-	account1 := &Account{
-		Address: Int64ToWord256(100),
-	}
-	account2 := &Account{
-		Address: Int64ToWord256(101),
-	}
+	account1 := newAccount(1)
+	account2 := newAccount(2)
 
-	var gas int64 = 100000
+	var gas uint64 = 100000
 	code := []byte{0x60, 0x10, 0x56} // jump to position 16, a clear failure
 	var err error
 	ch := make(chan struct{})
@@ -124,18 +119,14 @@ func TestJumpErr(t *testing.T) {
 func TestSubcurrency(t *testing.T) {
 	st := newAppState()
 	// Create accounts
-	account1 := &Account{
-		Address: LeftPadWord256(makeBytes(20)),
-	}
-	account2 := &Account{
-		Address: LeftPadWord256(makeBytes(20)),
-	}
-	st.accounts[account1.Address.String()] = account1
-	st.accounts[account2.Address.String()] = account2
+	account1 := newAccount(1, 2, 3)
+	account2 := newAccount(3, 2, 1)
+	st.accounts[account1.Address()] = account1
+	st.accounts[account2.Address()] = account2
 
-	ourVm := NewVM(st, DefaultDynamicMemoryProvider, newParams(), Zero256, nil)
+	ourVm := NewVM(st, DefaultDynamicMemoryProvider, newParams(), acm.ZeroAddress, nil, logger)
 
-	var gas int64 = 1000
+	var gas uint64 = 1000
 	code_parts := []string{"620f42403355",
 		"7c0100000000000000000000000000000000000000000000000000000000",
 		"600035046315cf268481141561004657",
@@ -143,7 +134,7 @@ func TestSubcurrency(t *testing.T) {
 		"60043560805260243560a052335460c0523360e05260a05160c05112151561008657",
 		"60a05160c0510360e0515560a0516080515401608051555b5b505b6000f3"}
 	code, _ := hex.DecodeString(strings.Join(code_parts, ""))
-	fmt.Printf("Code: %x\n", code)
+	fmt.Printf("Code: %s\n", code)
 	data, _ := hex.DecodeString("693200CE0000000000000000000000004B4363CDE27C2EB05E66357DB05BC5C88F850C1A0000000000000000000000000000000000000000000000000000000000000005")
 	output, err := ourVm.Call(account1, account2, code, data, 0, &gas)
 	fmt.Printf("Output: %v Error: %v\n", output, err)
@@ -155,21 +146,15 @@ func TestSubcurrency(t *testing.T) {
 // Test sending tokens from a contract to another account
 func TestSendCall(t *testing.T) {
 	fakeAppState := newAppState()
-	ourVm := NewVM(fakeAppState, DefaultDynamicMemoryProvider, newParams(), Zero256, nil)
+	ourVm := NewVM(fakeAppState, DefaultDynamicMemoryProvider, newParams(), acm.ZeroAddress, nil, logger)
 
 	// Create accounts
-	account1 := &Account{
-		Address: Int64ToWord256(100),
-	}
-	account2 := &Account{
-		Address: Int64ToWord256(101),
-	}
-	account3 := &Account{
-		Address: Int64ToWord256(102),
-	}
+	account1 := newAccount(1)
+	account2 := newAccount(2)
+	account3 := newAccount(3)
 
 	// account1 will call account2 which will trigger CALL opcode to account3
-	addr := account3.Address.Postfix(20)
+	addr := account3.Address()
 	contractCode := callContractCode(addr)
 
 	//----------------------------------------------
@@ -179,14 +164,13 @@ func TestSendCall(t *testing.T) {
 
 	//----------------------------------------------
 	// give account2 sufficient balance, should pass
-	account2.Balance = 100000
+	account2 = newAccount(2).AddToBalance(100000)
 	_, err = runVMWaitError(ourVm, account1, account2, addr, contractCode, 1000)
 	assert.NoError(t, err, "Should have sufficient balance")
 
 	//----------------------------------------------
 	// insufficient gas, should fail
-
-	account2.Balance = 100000
+	account2 = newAccount(2).AddToBalance(100000)
 	_, err = runVMWaitError(ourVm, account1, account2, addr, contractCode, 100)
 	assert.Error(t, err, "Expected insufficient gas error")
 }
@@ -197,8 +181,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) {
-	appState := newAppState()
-	ourVm := NewVM(appState, DefaultDynamicMemoryProvider, newParams(), Zero256, nil)
+	state := newAppState()
+	ourVm := NewVM(state, DefaultDynamicMemoryProvider, newParams(), acm.ZeroAddress, nil, logger)
 
 	inOff := 0
 	inSize := 0 // no call data
@@ -218,55 +202,55 @@ func TestDelegateCallGas(t *testing.T) {
 	costBetweenGasAndDelegateCall := gasCost + subCost + delegateCallCost + pushCost
 
 	// Do a simple operation using 1 gas unit
-	calleeAccount, calleeAddress := makeAccountWithCode(appState, "callee",
-		Bytecode(PUSH1, calleeReturnValue, return1()))
+	calleeAccount, calleeAddress := makeAccountWithCode(state, "callee",
+		Splice(PUSH1, calleeReturnValue, return1()))
 
 	// Here we split up the caller code so we can make a DELEGATE call with
 	// different amounts of gas. The value we sandwich in the middle is the amount
 	// we subtract from the available gas (that the caller has available), so:
-	// code := Bytecode(callerCodePrefix, <amount to subtract from GAS> , callerCodeSuffix)
+	// code := Splice(callerCodePrefix, <amount to subtract from GAS> , callerCodeSuffix)
 	// gives us the code to make the call
-	callerCodePrefix := Bytecode(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize,
+	callerCodePrefix := Splice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize,
 		PUSH1, inOff, PUSH20, calleeAddress, PUSH1)
-	callerCodeSuffix := Bytecode(GAS, SUB, DELEGATECALL, returnWord())
+	callerCodeSuffix := Splice(GAS, SUB, DELEGATECALL, returnWord())
 
 	// Perform a delegate call
-	callerAccount, _ := makeAccountWithCode(appState, "caller",
-		Bytecode(callerCodePrefix,
+	callerAccount, _ := makeAccountWithCode(state, "caller",
+		Splice(callerCodePrefix,
 			// Give just enough gas to make the DELEGATECALL
 			costBetweenGasAndDelegateCall,
 			callerCodeSuffix))
 
 	// Should pass
 	output, err := runVMWaitError(ourVm, callerAccount, calleeAccount, calleeAddress,
-		callerAccount.Code, 100)
+		callerAccount.Code(), 100)
 	assert.NoError(t, err, "Should have sufficient funds for call")
 	assert.Equal(t, Int64ToWord256(calleeReturnValue).Bytes(), output)
 
-	callerAccount.Code = Bytecode(callerCodePrefix,
+	callerAccount.SetCode(Splice(callerCodePrefix,
 		// Shouldn't be enough gas to make call
 		costBetweenGasAndDelegateCall-1,
-		callerCodeSuffix)
+		callerCodeSuffix))
 
 	// Should fail
 	_, err = runVMWaitError(ourVm, callerAccount, calleeAccount, calleeAddress,
-		callerAccount.Code, 100)
+		callerAccount.Code(), 100)
 	assert.Error(t, err, "Should have insufficient funds for call")
 }
 
 func TestMemoryBounds(t *testing.T) {
-	appState := newAppState()
+	state := newAppState()
 	memoryProvider := func() Memory {
 		return NewDynamicMemory(1024, 2048)
 	}
-	ourVm := NewVM(appState, memoryProvider, newParams(), Zero256, nil)
-	caller, _ := makeAccountWithCode(appState, "caller", nil)
-	callee, _ := makeAccountWithCode(appState, "callee", nil)
-	gas := int64(100000)
+	ourVm := NewVM(state, memoryProvider, newParams(), acm.ZeroAddress, nil, logger)
+	caller, _ := makeAccountWithCode(state, "caller", nil)
+	callee, _ := makeAccountWithCode(state, "callee", nil)
+	gas := uint64(100000)
 	// This attempts to store a value at the memory boundary and return it
 	word := One256
 	output, err := ourVm.call(caller, callee,
-		Bytecode(pushWord(word), storeAtEnd(), MLOAD, storeAtEnd(), returnAfterStore()),
+		Splice(pushWord(word), storeAtEnd(), MLOAD, storeAtEnd(), returnAfterStore()),
 		nil, 0, &gas)
 	assert.NoError(t, err)
 	assert.Equal(t, word.Bytes(), output)
@@ -274,7 +258,7 @@ func TestMemoryBounds(t *testing.T) {
 	// Same with number
 	word = Int64ToWord256(232234234432)
 	output, err = ourVm.call(caller, callee,
-		Bytecode(pushWord(word), storeAtEnd(), MLOAD, storeAtEnd(), returnAfterStore()),
+		Splice(pushWord(word), storeAtEnd(), MLOAD, storeAtEnd(), returnAfterStore()),
 		nil, 0, &gas)
 	assert.NoError(t, err)
 	assert.Equal(t, word.Bytes(), output)
@@ -282,9 +266,9 @@ func TestMemoryBounds(t *testing.T) {
 	// Now test a series of boundary stores
 	code := pushWord(word)
 	for i := 0; i < 10; i++ {
-		code = Bytecode(code, storeAtEnd(), MLOAD)
+		code = Splice(code, storeAtEnd(), MLOAD)
 	}
-	output, err = ourVm.call(caller, callee, Bytecode(code, storeAtEnd(), returnAfterStore()),
+	output, err = ourVm.call(caller, callee, Splice(code, storeAtEnd(), returnAfterStore()),
 		nil, 0, &gas)
 	assert.NoError(t, err)
 	assert.Equal(t, word.Bytes(), output)
@@ -292,9 +276,9 @@ func TestMemoryBounds(t *testing.T) {
 	// Same as above but we should breach the upper memory limit set in memoryProvider
 	code = pushWord(word)
 	for i := 0; i < 100; i++ {
-		code = Bytecode(code, storeAtEnd(), MLOAD)
+		code = Splice(code, storeAtEnd(), MLOAD)
 	}
-	output, err = ourVm.call(caller, callee, Bytecode(code, storeAtEnd(), returnAfterStore()),
+	output, err = ourVm.call(caller, callee, Splice(code, storeAtEnd(), returnAfterStore()),
 		nil, 0, &gas)
 	assert.Error(t, err, "Should hit memory out of bounds")
 }
@@ -307,49 +291,44 @@ func TestMemoryBounds(t *testing.T) {
 // stores that value at the current memory boundary
 func storeAtEnd() []byte {
 	// Pull in MSIZE (to carry forward to MLOAD), swap in value to store, store it at MSIZE
-	return Bytecode(MSIZE, SWAP1, DUP2, MSTORE)
+	return Splice(MSIZE, SWAP1, DUP2, MSTORE)
 }
 
 func returnAfterStore() []byte {
-	return Bytecode(PUSH1, 32, DUP2, RETURN)
+	return Splice(PUSH1, 32, DUP2, RETURN)
 }
 
 // Store the top element of the stack (which is a 32-byte word) in memory
 // and return it. Useful for a simple return value.
 func return1() []byte {
-	return Bytecode(PUSH1, 0, MSTORE, returnWord())
+	return Splice(PUSH1, 0, MSTORE, returnWord())
 }
 
 func returnWord() []byte {
 	// PUSH1 => return size, PUSH1 => return offset, RETURN
-	return Bytecode(PUSH1, 32, PUSH1, 0, RETURN)
+	return Splice(PUSH1, 32, PUSH1, 0, RETURN)
 }
 
-func makeAccountWithCode(appState AppState, name string,
-	code []byte) (*Account, []byte) {
-	account := &Account{
-		Address: LeftPadWord256([]byte(name)),
-		Balance: 9999999,
-		Code:    code,
-		Nonce:   0,
-	}
-	account.Code = code
-	appState.UpdateAccount(account)
-	// Sanity check
-	address := new([20]byte)
-	for i, b := range account.Address.Postfix(20) {
-		address[i] = b
-	}
-	return account, address[:]
+func makeAccountWithCode(state acm.Updater, name string,
+	code []byte) (acm.MutableAccount, acm.Address) {
+	address, _ := acm.AddressFromBytes([]byte(name))
+	account := acm.ConcreteAccount{
+		Address:  address,
+		Balance:  9999999,
+		Code:     code,
+		Sequence: 0,
+	}.MutableAccount()
+	state.UpdateAccount(account)
+	return account, account.Address()
 }
 
 // Subscribes to an AccCall, runs the vm, returns the output any direct exception
-// and then waits for any exceptions transmitted by EventData in the AccCall
+// and then waits for any exceptions transmitted by Data in the AccCall
 // event (in the case of no direct error from call we will block waiting for
 // at least 1 AccCall event)
-func runVMWaitError(ourVm *VM, caller, callee *Account, subscribeAddr,
-	contractCode []byte, gas int64) (output []byte, err error) {
-	eventCh := make(chan txs.EventData)
+func runVMWaitError(ourVm *VM, caller, callee acm.MutableAccount, subscribeAddr acm.Address,
+	contractCode []byte, gas uint64) (output []byte, err error) {
+	eventCh := make(chan event.EventData)
 	output, err = runVM(eventCh, ourVm, caller, callee, subscribeAddr,
 		contractCode, gas)
 	if err != nil {
@@ -357,10 +336,10 @@ func runVMWaitError(ourVm *VM, caller, callee *Account, subscribeAddr,
 	}
 	msg := <-eventCh
 	var errString string
-	switch ev := msg.(type) {
-	case txs.EventDataTx:
+	switch ev := msg.Unwrap().(type) {
+	case exe_events.EventDataTx:
 		errString = ev.Exception
-	case txs.EventDataCall:
+	case evm_events.EventDataCall:
 		errString = ev.Exception
 	}
 
@@ -372,18 +351,17 @@ func runVMWaitError(ourVm *VM, caller, callee *Account, subscribeAddr,
 
 // Subscribes to an AccCall, runs the vm, returns the output and any direct
 // exception
-func runVM(eventCh chan txs.EventData, ourVm *VM, caller, callee *Account,
-	subscribeAddr, contractCode []byte, gas int64) ([]byte, error) {
+func runVM(eventCh chan event.EventData, ourVm *VM, caller, callee acm.MutableAccount,
+	subscribeAddr acm.Address, contractCode []byte, gas uint64) ([]byte, error) {
 
 	// we need to catch the event from the CALL to check for exceptions
-	evsw := events.NewEventSwitch()
-	evsw.Start()
-	fmt.Printf("subscribe to %x\n", subscribeAddr)
-	evsw.AddListenerForEvent("test", txs.EventStringAccCall(subscribeAddr),
-		func(msg events.EventData) {
-			eventCh <- msg.(txs.EventData)
+	evsw := event.NewEmitter(loggers.NewNoopInfoTraceLogger())
+	fmt.Printf("subscribe to %s\n", subscribeAddr)
+	evsw.Subscribe("test", evm_events.EventStringAccCall(subscribeAddr),
+		func(msg event.AnyEventData) {
+			eventCh <- *msg.BurrowEventData
 		})
-	evc := events.NewEventCache(evsw)
+	evc := event.NewEventCache(evsw)
 	ourVm.SetFireable(evc)
 	start := time.Now()
 	output, err := ourVm.Call(caller, callee, contractCode, []byte{}, 0, &gas)
@@ -394,13 +372,13 @@ func runVM(eventCh chan txs.EventData, ourVm *VM, caller, callee *Account,
 }
 
 // this is code to call another contract (hardcoded as addr)
-func callContractCode(addr []byte) []byte {
+func callContractCode(addr acm.Address) []byte {
 	gas1, gas2 := byte(0x1), byte(0x1)
 	value := byte(0x69)
 	inOff, inSize := byte(0x0), byte(0x0) // no call data
 	retOff, retSize := byte(0x0), byte(0x20)
 	// this is the code we want to run (send funds to an account and return)
-	return Bytecode(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1,
+	return Splice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1,
 		inOff, PUSH1, value, PUSH20, addr, PUSH2, gas1, gas2, CALL, PUSH1, retSize,
 		PUSH1, retOff, RETURN)
 }
@@ -417,50 +395,50 @@ func pushWord(word Word256) []byte {
 		if word[leadingZeros] == 0 {
 			leadingZeros++
 		} else {
-			return Bytecode(byte(PUSH32)-leadingZeros, word[leadingZeros:])
+			return Splice(byte(PUSH32)-leadingZeros, word[leadingZeros:])
 		}
 	}
-	return Bytecode(PUSH1, 0)
+	return Splice(PUSH1, 0)
 }
 
 func TestPushWord(t *testing.T) {
 	word := Int64ToWord256(int64(2133213213))
-	assert.Equal(t, Bytecode(PUSH4, 0x7F, 0x26, 0x40, 0x1D), pushWord(word))
+	assert.Equal(t, Splice(PUSH4, 0x7F, 0x26, 0x40, 0x1D), pushWord(word))
 	word[0] = 1
-	assert.Equal(t, Bytecode(PUSH32,
+	assert.Equal(t, Splice(PUSH32,
 		1, 0, 0, 0, 0, 0, 0, 0,
 		0, 0, 0, 0, 0, 0, 0, 0,
 		0, 0, 0, 0, 0, 0, 0, 0,
 		0, 0, 0, 0, 0x7F, 0x26, 0x40, 0x1D), pushWord(word))
-	assert.Equal(t, Bytecode(PUSH1, 0), pushWord(Word256{}))
-	assert.Equal(t, Bytecode(PUSH1, 1), pushWord(Int64ToWord256(1)))
+	assert.Equal(t, Splice(PUSH1, 0), pushWord(Word256{}))
+	assert.Equal(t, Splice(PUSH1, 1), pushWord(Int64ToWord256(1)))
 }
 
 func TestBytecode(t *testing.T) {
 	assert.Equal(t,
-		Bytecode(1, 2, 3, 4, 5, 6),
-		Bytecode(1, 2, 3, Bytecode(4, 5, 6)))
+		Splice(1, 2, 3, 4, 5, 6),
+		Splice(1, 2, 3, Splice(4, 5, 6)))
 	assert.Equal(t,
-		Bytecode(1, 2, 3, 4, 5, 6, 7, 8),
-		Bytecode(1, 2, 3, Bytecode(4, Bytecode(5), 6), 7, 8))
+		Splice(1, 2, 3, 4, 5, 6, 7, 8),
+		Splice(1, 2, 3, Splice(4, Splice(5), 6), 7, 8))
 	assert.Equal(t,
-		Bytecode(PUSH1, 2),
-		Bytecode(byte(PUSH1), 0x02))
+		Splice(PUSH1, 2),
+		Splice(byte(PUSH1), 0x02))
 	assert.Equal(t,
 		[]byte{},
-		Bytecode(Bytecode(Bytecode())))
+		Splice(Splice(Splice())))
 
-	contractAccount := &Account{Address: Int64ToWord256(102)}
-	addr := contractAccount.Address.Postfix(20)
+	contractAccount := &acm.ConcreteAccount{Address: acm.AddressFromWord256(Int64ToWord256(102))}
+	addr := contractAccount.Address
 	gas1, gas2 := byte(0x1), byte(0x1)
 	value := byte(0x69)
 	inOff, inSize := byte(0x0), byte(0x0) // no call data
 	retOff, retSize := byte(0x0), byte(0x20)
-	contractCodeBytecode := Bytecode(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1,
+	contractCodeBytecode := Splice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1,
 		inOff, PUSH1, value, PUSH20, addr, PUSH2, gas1, gas2, CALL, PUSH1, retSize,
 		PUSH1, retOff, RETURN)
 	contractCode := []byte{0x60, retSize, 0x60, retOff, 0x60, inSize, 0x60, inOff, 0x60, value, 0x73}
-	contractCode = append(contractCode, addr...)
+	contractCode = append(contractCode, addr[:]...)
 	contractCode = append(contractCode, []byte{0x61, gas1, gas2, 0xf1, 0x60, 0x20, 0x60, 0x0, 0xf3}...)
 	assert.Equal(t, contractCode, contractCodeBytecode)
 }
diff --git a/manager/burrow-mint/state/execution.go b/execution/execution.go
similarity index 54%
rename from manager/burrow-mint/state/execution.go
rename to execution/execution.go
index 4c765ec7..cf634233 100644
--- a/manager/burrow-mint/state/execution.go
+++ b/execution/execution.go
@@ -12,341 +12,170 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package state
+package execution
 
 import (
-	"bytes"
 	"fmt"
+	"sync"
 
 	acm "github.com/hyperledger/burrow/account"
-	"github.com/hyperledger/burrow/common/sanity"
-	core_types "github.com/hyperledger/burrow/core/types"
+	"github.com/hyperledger/burrow/binary"
+	bcm "github.com/hyperledger/burrow/blockchain"
+	"github.com/hyperledger/burrow/event"
+	"github.com/hyperledger/burrow/execution/events"
+	"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/manager/burrow-mint/evm"
-	ptypes "github.com/hyperledger/burrow/permission/types" // for GlobalPermissionAddress ...
+	"github.com/hyperledger/burrow/permission"
+	ptypes "github.com/hyperledger/burrow/permission/types"
 	"github.com/hyperledger/burrow/txs"
-	. "github.com/hyperledger/burrow/word256"
-
-	"github.com/hyperledger/burrow/logging"
-	"github.com/tendermint/go-events"
 )
 
-// ExecBlock stuff is now taken care of by the consensus engine.
-// But we leave here for now for reference when we have to do validator updates
-
-/*
-
-// NOTE: If an error occurs during block execution, state will be left
-// at an invalid state.  Copy the state before calling ExecBlock!
-func ExecBlock(s *State, block *txs.Block, blockPartsHeader txs.PartSetHeader) error {
-	err := execBlock(s, block, blockPartsHeader)
-	if err != nil {
-		return err
-	}
-	// State.Hash should match block.StateHash
-	stateHash := s.Hash()
-	if !bytes.Equal(stateHash, block.StateHash) {
-		return errors.New(Fmt("Invalid state hash. Expected %X, got %X",
-			stateHash, block.StateHash))
-	}
-	return nil
+type BatchExecutor interface {
+	acm.StateIterable
+	acm.Updater
+	acm.StorageSetter
+	// Execute transaction against block cache (i.e. block buffer)
+	Execute(tx txs.Tx) error
+	// Reset executor to underlying State
+	Reset() error
 }
 
-// executes transactions of a block, does not check block.StateHash
-// NOTE: If an error occurs during block execution, state will be left
-// at an invalid state.  Copy the state before calling execBlock!
-func execBlock(s *State, block *txs.Block, blockPartsHeader txs.PartSetHeader) error {
-	// Basic block validation.
-	err := block.ValidateBasic(s.ChainID, s.LastBlockHeight, s.LastBlockHash, s.LastBlockParts, s.LastBlockTime)
-	if err != nil {
-		return err
-	}
-
-	// Validate block LastValidation.
-	if block.Height == 1 {
-		if len(block.LastValidation.Precommits) != 0 {
-			return errors.New("Block at height 1 (first block) should have no LastValidation precommits")
-		}
-	} else {
-		if len(block.LastValidation.Precommits) != s.LastBondedValidators.Size() {
-			return errors.New(Fmt("Invalid block validation size. Expected %v, got %v",
-				s.LastBondedValidators.Size(), len(block.LastValidation.Precommits)))
-		}
-		err := s.LastBondedValidators.VerifyValidation(
-			s.ChainID, s.LastBlockHash, s.LastBlockParts, block.Height-1, block.LastValidation)
-		if err != nil {
-			return err
-		}
-	}
-
-	// Update Validator.LastCommitHeight as necessary.
-	for i, precommit := range block.LastValidation.Precommits {
-		if precommit == nil {
-			continue
-		}
-		_, val := s.LastBondedValidators.GetByIndex(i)
-		if val == nil {
-			PanicCrisis(Fmt("Failed to fetch validator at index %v", i))
-		}
-		if _, val_ := s.BondedValidators.GetByAddress(val.Address); val_ != nil {
-			val_.LastCommitHeight = block.Height - 1
-			updated := s.BondedValidators.Update(val_)
-			if !updated {
-				PanicCrisis("Failed to update bonded validator LastCommitHeight")
-			}
-		} else if _, val_ := s.UnbondingValidators.GetByAddress(val.Address); val_ != nil {
-			val_.LastCommitHeight = block.Height - 1
-			updated := s.UnbondingValidators.Update(val_)
-			if !updated {
-				PanicCrisis("Failed to update unbonding validator LastCommitHeight")
-			}
-		} else {
-			PanicCrisis("Could not find validator")
-		}
-	}
-
-	// Remember LastBondedValidators
-	s.LastBondedValidators = s.BondedValidators.Copy()
-
-	// Create BlockCache to cache changes to state.
-	blockCache := NewBlockCache(s)
-
-	// Execute each tx
-	for _, tx := range block.Data.Txs {
-		err := ExecTx(blockCache, tx, true, s.evc)
-		if err != nil {
-			return InvalidTxError{tx, err}
-		}
-	}
+// Executes transactions
+type BatchCommitter interface {
+	BatchExecutor
+	// Commit execution results to underlying State and provide opportunity
+	// to mutate state before it is saved
+	Commit() (stateHash []byte, err error)
+}
 
-	// Now sync the BlockCache to the backend.
-	blockCache.Sync()
+type executor struct {
+	mtx        sync.Mutex
+	chainID    string
+	tip        bcm.Tip
+	runCall    bool
+	state      *State
+	blockCache *BlockCache
+	fireable   event.Fireable
+	eventCache *event.Cache
+	logger     logging_types.InfoTraceLogger
+}
 
-	// If any unbonding periods are over,
-	// reward account with bonded coins.
-	toRelease := []*txs.Validator{}
-	s.UnbondingValidators.Iterate(func(index int, val *txs.Validator) bool {
-		if val.UnbondHeight+unbondingPeriodBlocks < block.Height {
-			toRelease = append(toRelease, val)
-		}
-		return false
-	})
-	for _, val := range toRelease {
-		s.releaseValidator(val)
-	}
+var _ BatchExecutor = (*executor)(nil)
 
-	// If any validators haven't signed in a while,
-	// unbond them, they have timed out.
-	toTimeout := []*txs.Validator{}
-	s.BondedValidators.Iterate(func(index int, val *txs.Validator) bool {
-		lastActivityHeight := MaxInt(val.BondHeight, val.LastCommitHeight)
-		if lastActivityHeight+validatorTimeoutBlocks < block.Height {
-			log.Notice("Validator timeout", "validator", val, "height", block.Height)
-			toTimeout = append(toTimeout, val)
-		}
-		return false
-	})
-	for _, val := range toTimeout {
-		s.unbondValidator(val)
-	}
+// Wraps a cache of what is variously known as the 'check cache' and 'mempool'
+func NewBatchChecker(state *State,
+	chainID string,
+	tip bcm.Tip,
+	logger logging_types.InfoTraceLogger) BatchExecutor {
+	return newExecutor(false, state, chainID, tip, event.NewNoOpFireable(),
+		logging.WithScope(logger, "NewBatchExecutor"))
+}
 
-	// Increment validator AccumPowers
-	s.BondedValidators.IncrementAccum(1)
-	s.LastBlockHeight = block.Height
-	s.LastBlockHash = block.Hash()
-	s.LastBlockParts = blockPartsHeader
-	s.LastBlockTime = block.Time
-	return nil
+func NewBatchCommitter(state *State,
+	chainID string,
+	tip bcm.Tip,
+	fireable event.Fireable,
+	logger logging_types.InfoTraceLogger) BatchCommitter {
+	return newExecutor(true, state, chainID, tip, fireable,
+		logging.WithScope(logger, "NewBatchCommitter"))
 }
-*/
 
-// The accounts from the TxInputs must either already have
-// acm.PubKey.(type) != nil, (it must be known),
-// or it must be specified in the TxInput.  If redeclared,
-// the TxInput is modified and input.PubKey set to nil.
-func getInputs(state AccountGetter, ins []*txs.TxInput) (map[string]*acm.Account, error) {
-	accounts := map[string]*acm.Account{}
-	for _, in := range ins {
-		// Account shouldn't be duplicated
-		if _, ok := accounts[string(in.Address)]; ok {
-			return nil, txs.ErrTxDuplicateAddress
-		}
-		acc := state.GetAccount(in.Address)
-		if acc == nil {
-			return nil, txs.ErrTxInvalidAddress
-		}
-		// PubKey should be present in either "account" or "in"
-		if err := checkInputPubKey(acc, in); err != nil {
-			return nil, err
-		}
-		accounts[string(in.Address)] = acc
+func newExecutor(runCall bool,
+	state *State,
+	chainID string,
+	tip bcm.Tip,
+	eventFireable event.Fireable,
+	logger logging_types.InfoTraceLogger) *executor {
+	return &executor{
+		chainID:    chainID,
+		tip:        tip,
+		runCall:    runCall,
+		state:      state,
+		blockCache: NewBlockCache(state),
+		fireable:   eventFireable,
+		eventCache: event.NewEventCache(eventFireable),
+		logger:     logger.With(structure.ComponentKey, "Execution"),
 	}
-	return accounts, nil
 }
 
-func getOrMakeOutputs(state AccountGetter, accounts map[string]*acm.Account,
-	outs []*txs.TxOutput, logger logging_types.InfoTraceLogger) (map[string]*acm.Account, error) {
-	if accounts == nil {
-		accounts = make(map[string]*acm.Account)
-	}
+// Accounts
+func (exe *executor) GetAccount(address acm.Address) (acm.Account, error) {
+	return exe.blockCache.GetAccount(address)
+}
 
-	// we should err if an account is being created but the inputs don't have permission
-	var checkedCreatePerms bool
-	for _, out := range outs {
-		// Account shouldn't be duplicated
-		if _, ok := accounts[string(out.Address)]; ok {
-			return nil, txs.ErrTxDuplicateAddress
-		}
-		acc := state.GetAccount(out.Address)
-		// output account may be nil (new)
-		if acc == nil {
-			if !checkedCreatePerms {
-				if !hasCreateAccountPermission(state, accounts, logger) {
-					return nil, fmt.Errorf("At least one input does not have permission to create accounts")
-				}
-				checkedCreatePerms = true
-			}
-			acc = &acm.Account{
-				Address:     out.Address,
-				PubKey:      nil,
-				Sequence:    0,
-				Balance:     0,
-				Permissions: ptypes.ZeroAccountPermissions,
-			}
-		}
-		accounts[string(out.Address)] = acc
-	}
-	return accounts, nil
+func (exe *executor) UpdateAccount(account acm.Account) error {
+	return exe.blockCache.UpdateAccount(account)
 }
 
-// Since all ethereum accounts implicitly exist we sometimes lazily create an Account object to represent them
-// only when needed. Sometimes we need to create an unknown Account knowing only its address (which is expected to
-// be a deterministic hash of its associated public key) and not its public key. When we eventually receive a
-// transaction acting on behalf of that account we will be given a public key that we can check matches the address.
-// If it does then we will associate the public key with the stub account already registered in the system once and
-// for all time.
-func checkInputPubKey(acc *acm.Account, in *txs.TxInput) error {
-	if acc.PubKey == nil {
-		if in.PubKey == nil {
-			return txs.ErrTxUnknownPubKey
-		}
-		if !bytes.Equal(in.PubKey.Address(), acc.Address) {
-			return txs.ErrTxInvalidPubKey
-		}
-		acc.PubKey = in.PubKey
-	} else {
-		in.PubKey = nil
-	}
-	return nil
+func (exe *executor) RemoveAccount(address acm.Address) error {
+	return exe.blockCache.RemoveAccount(address)
 }
 
-func validateInputs(accounts map[string]*acm.Account, signBytes []byte, ins []*txs.TxInput) (total int64, err error) {
-	for _, in := range ins {
-		acc := accounts[string(in.Address)]
-		if acc == nil {
-			sanity.PanicSanity("validateInputs() expects account in accounts")
-		}
-		err = validateInput(acc, signBytes, in)
-		if err != nil {
-			return
-		}
-		// Good. Add amount to total
-		total += in.Amount
-	}
-	return total, nil
+func (exe *executor) IterateAccounts(consumer func(acm.Account) bool) (bool, error) {
+	return exe.blockCache.IterateAccounts(consumer)
 }
 
-func validateInput(acc *acm.Account, signBytes []byte, in *txs.TxInput) (err error) {
-	// Check TxInput basic
-	if err := in.ValidateBasic(); err != nil {
-		return err
-	}
-	// Check signatures
-	if !acc.PubKey.VerifyBytes(signBytes, in.Signature) {
-		return txs.ErrTxInvalidSignature
-	}
-	// Check sequences
-	if acc.Sequence+1 != in.Sequence {
-		return txs.ErrTxInvalidSequence{
-			Got:      in.Sequence,
-			Expected: acc.Sequence + 1,
-		}
-	}
-	// Check amount
-	if acc.Balance < in.Amount {
-		return txs.ErrTxInsufficientFunds
-	}
-	return nil
+// Storage
+func (exe *executor) GetStorage(address acm.Address, key binary.Word256) (binary.Word256, error) {
+	return exe.blockCache.GetStorage(address, key)
 }
 
-func validateOutputs(outs []*txs.TxOutput) (total int64, err error) {
-	for _, out := range outs {
-		// Check TxOutput basic
-		if err := out.ValidateBasic(); err != nil {
-			return 0, err
-		}
-		// Good. Add amount to total
-		total += out.Amount
-	}
-	return total, nil
+func (exe *executor) SetStorage(address acm.Address, key binary.Word256, value binary.Word256) error {
+	return exe.blockCache.SetStorage(address, key, value)
 }
 
-func adjustByInputs(accounts map[string]*acm.Account, ins []*txs.TxInput) {
-	for _, in := range ins {
-		acc := accounts[string(in.Address)]
-		if acc == nil {
-			sanity.PanicSanity("adjustByInputs() expects account in accounts")
-		}
-		if acc.Balance < in.Amount {
-			sanity.PanicSanity("adjustByInputs() expects sufficient funds")
-		}
-		acc.Balance -= in.Amount
+func (exe *executor) IterateStorage(address acm.Address, consumer func(key, value binary.Word256) bool) (bool, error) {
+	return exe.blockCache.IterateStorage(address, consumer)
+}
 
-		acc.Sequence += 1
-	}
+func (exe *executor) Commit() ([]byte, error) {
+	exe.mtx.Lock()
+	defer exe.mtx.Unlock()
+	// sync the cache
+	exe.blockCache.Sync()
+	// save state to disk
+	exe.state.Save()
+	// flush events to listeners (XXX: note issue with blocking)
+	exe.eventCache.Flush()
+	return exe.state.Hash(), nil
 }
 
-func adjustByOutputs(accounts map[string]*acm.Account, outs []*txs.TxOutput) {
-	for _, out := range outs {
-		acc := accounts[string(out.Address)]
-		if acc == nil {
-			sanity.PanicSanity("adjustByOutputs() expects account in accounts")
-		}
-		acc.Balance += out.Amount
-	}
+func (exe *executor) Reset() error {
+	exe.blockCache = NewBlockCache(exe.state)
+	exe.eventCache = event.NewEventCache(exe.fireable)
+	return nil
 }
 
 // If the tx is invalid, an error will be returned.
 // Unlike ExecBlock(), state will not be altered.
-func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable,
-	logger logging_types.InfoTraceLogger) (err error) {
-
-	logger = logging.WithScope(logger, "ExecTx")
+func (exe *executor) Execute(tx txs.Tx) error {
+	logger := logging.WithScope(exe.logger, "executor.Execute(tx txs.Tx)")
 	// TODO: do something with fees
-	fees := int64(0)
-	_s := blockCache.State() // hack to access validators and block height
+	fees := uint64(0)
 
 	// Exec tx
 	switch tx := tx.(type) {
 	case *txs.SendTx:
-		accounts, err := getInputs(blockCache, tx.Inputs)
+		accounts, err := getInputs(exe.blockCache, tx.Inputs)
 		if err != nil {
 			return err
 		}
 
 		// ensure all inputs have send permissions
-		if !hasSendPermission(blockCache, accounts, logger) {
-			return fmt.Errorf("At least one input lacks permission for SendTx")
+		if !hasSendPermission(exe.blockCache, accounts, logger) {
+			return fmt.Errorf("at least one input lacks permission for SendTx")
 		}
 
 		// add outputs to accounts map
 		// if any outputs don't exist, all inputs must have CreateAccount perm
-		accounts, err = getOrMakeOutputs(blockCache, accounts, tx.Outputs, logger)
+		accounts, err = getOrMakeOutputs(exe.blockCache, accounts, tx.Outputs, logger)
 		if err != nil {
 			return err
 		}
 
-		signBytes := acm.SignBytes(_s.ChainID, tx)
+		signBytes := acm.SignBytes(exe.chainID, tx)
 		inTotal, err := validateInputs(accounts, signBytes, tx.Inputs)
 		if err != nil {
 			return err
@@ -365,40 +194,44 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 		adjustByInputs(accounts, tx.Inputs)
 		adjustByOutputs(accounts, tx.Outputs)
 		for _, acc := range accounts {
-			blockCache.UpdateAccount(acc)
+			exe.blockCache.UpdateAccount(acc)
 		}
 
-		// if the evc is nil, nothing will happen
-		if evc != nil {
+		// if the exe.eventCache is nil, nothing will happen
+		if exe.eventCache != nil {
 			for _, i := range tx.Inputs {
-				evc.FireEvent(txs.EventStringAccInput(i.Address), txs.EventDataTx{tx, nil, ""})
+				exe.eventCache.Fire(events.EventStringAccInput(i.Address), events.EventDataTx{tx, nil, ""})
 			}
 
 			for _, o := range tx.Outputs {
-				evc.FireEvent(txs.EventStringAccOutput(o.Address), txs.EventDataTx{tx, nil, ""})
+				exe.eventCache.Fire(events.EventStringAccOutput(o.Address), events.EventDataTx{tx, nil, ""})
 			}
 		}
 		return nil
 
 	case *txs.CallTx:
-		var inAcc, outAcc *acm.Account
+		var inAcc acm.MutableAccount
+		var outAcc acm.Account
 
 		// Validate input
-		inAcc = blockCache.GetAccount(tx.Input.Address)
+		inAcc, err := acm.GetMutableAccount(exe.blockCache, tx.Input.Address)
+		if err != nil {
+			return err
+		}
 		if inAcc == nil {
 			logging.InfoMsg(logger, "Cannot find input account",
 				"tx_input", tx.Input)
 			return txs.ErrTxInvalidAddress
 		}
 
-		createContract := len(tx.Address) == 0
+		createContract := tx.Address == nil
 		if createContract {
-			if !hasCreateContractPermission(blockCache, inAcc, logger) {
-				return fmt.Errorf("Account %X does not have CreateContract permission", tx.Input.Address)
+			if !hasCreateContractPermission(exe.blockCache, inAcc, logger) {
+				return fmt.Errorf("account %s does not have CreateContract permission", tx.Input.Address)
 			}
 		} else {
-			if !hasCallPermission(blockCache, inAcc, logger) {
-				return fmt.Errorf("Account %X does not have Call permission", tx.Input.Address)
+			if !hasCallPermission(exe.blockCache, inAcc, logger) {
+				return fmt.Errorf("account %s does not have Call permission", tx.Input.Address)
 			}
 		}
 
@@ -408,8 +241,8 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 				"tx_input", tx.Input)
 			return err
 		}
-		signBytes := acm.SignBytes(_s.ChainID, tx)
-		err := validateInput(inAcc, signBytes, tx.Input)
+		signBytes := acm.SignBytes(exe.chainID, tx)
+		err = validateInput(inAcc, signBytes, tx.Input)
 		if err != nil {
 			logging.InfoMsg(logger, "validateInput failed",
 				"tx_input", tx.Input, "error", err)
@@ -422,24 +255,22 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 		}
 
 		if !createContract {
-			// Validate output
-			if len(tx.Address) != 20 {
-				logging.InfoMsg(logger, "Destination address is not 20 bytes",
-					"address", tx.Address)
-				return txs.ErrTxInvalidAddress
-			}
 			// check if its a native contract
-			if vm.RegisteredNativeContract(LeftPadWord256(tx.Address)) {
-				return fmt.Errorf("Attempt to call a native contract at %X, "+
+			if evm.RegisteredNativeContract(tx.Address.Word256()) {
+				return fmt.Errorf("attempt to call a native contract at %s, "+
 					"but native contracts cannot be called using CallTx. Use a "+
 					"contract that calls the native contract or the appropriate tx "+
-					"type (eg. PermissionsTx, NameTx).", tx.Address)
+					"type (eg. PermissionsTx, NameTx)", tx.Address)
 			}
 
 			// Output account may be nil if we are still in mempool and contract was created in same block as this tx
 			// but that's fine, because the account will be created properly when the create tx runs in the block
 			// and then this won't return nil. otherwise, we take their fee
-			outAcc = blockCache.GetAccount(tx.Address)
+			// Note: tx.Address == nil iff createContract so dereference is okay
+			outAcc, err = exe.blockCache.GetAccount(*tx.Address)
+			if err != nil {
+				return err
+			}
 		}
 
 		logger.Trace("output_account", outAcc)
@@ -447,31 +278,35 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 		// Good!
 		value := tx.Input.Amount - tx.Fee
 
-		inAcc.Sequence += 1
-		inAcc.Balance -= tx.Fee
-		blockCache.UpdateAccount(inAcc)
+		logging.TraceMsg(logger, "Incrementing sequence number",
+			"account", inAcc.Address(),
+			"old_sequence", inAcc.Sequence(),
+			"new_sequence", inAcc.Sequence()+1)
+		inAcc.IncSequence().SubtractFromBalance(tx.Fee)
+
+		exe.blockCache.UpdateAccount(inAcc)
 
 		// The logic in runCall MUST NOT return.
-		if runCall {
+		if exe.runCall {
 
 			// VM call variables
 			var (
-				gas     int64       = tx.GasLimit
-				err     error       = nil
-				caller  *vm.Account = toVMAccount(inAcc)
-				callee  *vm.Account = nil // initialized below
-				code    []byte      = nil
-				ret     []byte      = nil
-				txCache             = NewTxCache(blockCache)
-				params              = vm.Params{
-					BlockHeight: int64(_s.LastBlockHeight),
-					BlockHash:   LeftPadWord256(_s.LastBlockHash),
-					BlockTime:   _s.LastBlockTime.Unix(),
-					GasLimit:    _s.GetGasLimit(),
+				gas     uint64             = tx.GasLimit
+				err     error              = nil
+				caller  acm.MutableAccount = acm.AsMutableAccount(inAcc)
+				callee  acm.MutableAccount = nil // initialized below
+				code    []byte             = nil
+				ret     []byte             = nil
+				txCache                    = NewTxCache(exe.blockCache)
+				params                     = evm.Params{
+					BlockHeight: exe.tip.LastBlockHeight(),
+					BlockHash:   binary.LeftPadWord256(exe.tip.LastBlockHash()),
+					BlockTime:   exe.tip.LastBlockTime().Unix(),
+					GasLimit:    GasLimit,
 				}
 			)
 
-			if !createContract && (outAcc == nil || len(outAcc.Code) == 0) {
+			if !createContract && (outAcc == nil || len(outAcc.Code()) == 0) {
 				// if you call an account that doesn't exist
 				// or an account with no code then we take fees (sorry pal)
 				// NOTE: it's fine to create a contract and call it within one
@@ -495,28 +330,28 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 			// get or create callee
 			if createContract {
 				// We already checked for permission
-				callee = txCache.CreateAccount(caller)
+				callee = evm.DeriveNewAccount(caller, permission.GlobalAccountPermissions(exe.state))
 				logging.TraceMsg(logger, "Created new contract",
 					"contract_address", callee.Address,
 					"contract_code", callee.Code)
 				code = tx.Data
 			} else {
-				callee = toVMAccount(outAcc)
+				callee = acm.AsMutableAccount(outAcc)
 				logging.TraceMsg(logger, "Calling existing contract",
 					"contract_address", callee.Address,
 					"contract_code", callee.Code)
-				code = callee.Code
+				code = callee.Code()
 			}
-			logger.Trace("callee_")
+			logger.Trace("callee", callee.Address().String())
 
-			// Run VM call and sync txCache to blockCache.
+			// 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 := vm.NewVM(txCache, vm.DefaultDynamicMemoryProvider, params,
-					caller.Address, txs.TxHash(_s.ChainID, tx))
-				vmach.SetFireable(evc)
+				vmach := evm.NewVM(txCache, evm.DefaultDynamicMemoryProvider, params, caller.Address(),
+					txs.TxHash(exe.chainID, tx), logger)
+				vmach.SetFireable(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 {
@@ -528,9 +363,9 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 
 				logging.TraceMsg(logger, "Successful execution")
 				if createContract {
-					callee.Code = ret
+					callee.SetCode(ret)
 				}
-				txCache.Sync()
+				txCache.Sync(exe.blockCache)
 			}
 
 		CALL_COMPLETE: // err may or may not be nil.
@@ -544,41 +379,52 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 
 			// Fire Events for sender and receiver
 			// a separate event will be fired from vm for each additional call
-			if evc != nil {
+			if exe.eventCache != nil {
 				exception := ""
 				if err != nil {
 					exception = err.Error()
 				}
-				evc.FireEvent(txs.EventStringAccInput(tx.Input.Address), txs.EventDataTx{tx, ret, exception})
-				evc.FireEvent(txs.EventStringAccOutput(tx.Address), txs.EventDataTx{tx, ret, exception})
+				exe.eventCache.Fire(events.EventStringAccInput(tx.Input.Address),
+					events.EventDataTx{tx, ret, exception})
+				if tx.Address != nil {
+					exe.eventCache.Fire(events.EventStringAccOutput(*tx.Address),
+						events.EventDataTx{tx, ret, exception})
+				}
 			}
 		} else {
 			// The mempool does not call txs until
 			// the proposer determines the order of txs.
 			// So mempool will skip the actual .Call(),
 			// and only deduct from the caller's balance.
-			inAcc.Balance -= value
+			inAcc.SubtractFromBalance(value)
 			if createContract {
-				inAcc.Sequence += 1 // XXX ?!
+				// This is done by DeriveNewAccount when runCall == true
+
+				logging.TraceMsg(logger, "Incrementing sequence number since creates contract",
+					"account", inAcc.Address(),
+					"old_sequence", inAcc.Sequence(),
+					"new_sequence", inAcc.Sequence()+1)
+				inAcc.IncSequence()
 			}
-			blockCache.UpdateAccount(inAcc)
+			exe.blockCache.UpdateAccount(inAcc)
 		}
 
 		return nil
 
 	case *txs.NameTx:
-		var inAcc *acm.Account
-
 		// Validate input
-		inAcc = blockCache.GetAccount(tx.Input.Address)
+		inAcc, err := acm.GetMutableAccount(exe.blockCache, tx.Input.Address)
+		if err != nil {
+			return err
+		}
 		if inAcc == nil {
 			logging.InfoMsg(logger, "Cannot find input account",
 				"tx_input", tx.Input)
 			return txs.ErrTxInvalidAddress
 		}
 		// check permission
-		if !hasNamePermission(blockCache, inAcc, logger) {
-			return fmt.Errorf("Account %X does not have Name permission", tx.Input.Address)
+		if !hasNamePermission(exe.blockCache, inAcc, logger) {
+			return fmt.Errorf("account %s does not have Name permission", tx.Input.Address)
 		}
 		// pubKey should be present in either "inAcc" or "tx.Input"
 		if err := checkInputPubKey(inAcc, tx.Input); err != nil {
@@ -586,8 +432,8 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 				"tx_input", tx.Input)
 			return err
 		}
-		signBytes := acm.SignBytes(_s.ChainID, tx)
-		err := validateInput(inAcc, signBytes, tx.Input)
+		signBytes := acm.SignBytes(exe.chainID, tx)
+		err = validateInput(inAcc, signBytes, tx.Input)
 		if err != nil {
 			logging.InfoMsg(logger, "validateInput failed",
 				"tx_input", tx.Input, "error", err)
@@ -608,8 +454,8 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 
 		// let's say cost of a name for one block is len(data) + 32
 		costPerBlock := txs.NameCostPerBlock(txs.NameBaseCost(tx.Name, tx.Data))
-		expiresIn := int(value / costPerBlock)
-		lastBlockHeight := _s.LastBlockHeight
+		expiresIn := value / uint64(costPerBlock)
+		lastBlockHeight := exe.tip.LastBlockHeight()
 
 		logging.TraceMsg(logger, "New NameTx",
 			"value", value,
@@ -618,7 +464,7 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 			"last_block_height", lastBlockHeight)
 
 		// check if the name exists
-		entry := blockCache.GetNameRegEntry(tx.Name)
+		entry := exe.blockCache.GetNameRegEntry(tx.Name)
 
 		if entry != nil {
 			var expired bool
@@ -626,11 +472,9 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 			// if the entry already exists, and hasn't expired, we must be owner
 			if entry.Expires > lastBlockHeight {
 				// ensure we are owner
-				if !bytes.Equal(entry.Owner, tx.Input.Address) {
-					logging.InfoMsg(logger, "Sender is trying to update a name for which they are not an owner",
-						"sender_address", tx.Input.Address,
-						"name", tx.Name)
-					return txs.ErrTxPermissionDenied
+				if entry.Owner != tx.Input.Address {
+					return fmt.Errorf("permission denied: sender %s is trying to update a name (%s) for "+
+						"which they are not an owner", tx.Input.Address, tx.Name)
 				}
 			} else {
 				expired = true
@@ -642,7 +486,7 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 				// (owners if not expired, anyone if expired)
 				logging.TraceMsg(logger, "Removing NameReg entry (no value and empty data in tx requests this)",
 					"name", entry.Name)
-				blockCache.RemoveNameRegEntry(entry.Name)
+				exe.blockCache.RemoveNameRegEntry(entry.Name)
 			} else {
 				// update the entry by bumping the expiry
 				// and changing the data
@@ -659,11 +503,11 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 				} else {
 					// since the size of the data may have changed
 					// we use the total amount of "credit"
-					oldCredit := int64(entry.Expires-lastBlockHeight) * txs.NameBaseCost(entry.Name, entry.Data)
+					oldCredit := (entry.Expires - lastBlockHeight) * txs.NameBaseCost(entry.Name, entry.Data)
 					credit := oldCredit + value
-					expiresIn = int(credit / costPerBlock)
+					expiresIn = uint64(credit / costPerBlock)
 					if expiresIn < txs.MinNameRegistrationPeriod {
-						return fmt.Errorf("Names must be registered for at least %d blocks", txs.MinNameRegistrationPeriod)
+						return fmt.Errorf("names must be registered for at least %d blocks", txs.MinNameRegistrationPeriod)
 					}
 					entry.Expires = lastBlockHeight + expiresIn
 					logging.TraceMsg(logger, "Updated NameReg entry",
@@ -674,14 +518,14 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 						"credit", credit)
 				}
 				entry.Data = tx.Data
-				blockCache.UpdateNameRegEntry(entry)
+				exe.blockCache.UpdateNameRegEntry(entry)
 			}
 		} else {
 			if expiresIn < txs.MinNameRegistrationPeriod {
 				return fmt.Errorf("Names must be registered for at least %d blocks", txs.MinNameRegistrationPeriod)
 			}
 			// entry does not exist, so create it
-			entry = &core_types.NameRegEntry{
+			entry = &NameRegEntry{
 				Name:    tx.Name,
 				Owner:   tx.Input.Address,
 				Data:    tx.Data,
@@ -690,21 +534,21 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 			logging.TraceMsg(logger, "Creating NameReg entry",
 				"name", entry.Name,
 				"expires_in", expiresIn)
-			blockCache.UpdateNameRegEntry(entry)
+			exe.blockCache.UpdateNameRegEntry(entry)
 		}
 
 		// TODO: something with the value sent?
 
 		// Good!
-		inAcc.Sequence += 1
-		inAcc.Balance -= value
-		blockCache.UpdateAccount(inAcc)
+		inAcc.IncSequence()
+		inAcc.SubtractFromBalance(value)
+		exe.blockCache.UpdateAccount(inAcc)
 
 		// TODO: maybe we want to take funds on error and allow txs in that don't do anythingi?
 
-		if evc != nil {
-			evc.FireEvent(txs.EventStringAccInput(tx.Input.Address), txs.EventDataTx{tx, nil, ""})
-			evc.FireEvent(txs.EventStringNameReg(tx.Name), txs.EventDataTx{tx, nil, ""})
+		if exe.eventCache != nil {
+			exe.eventCache.Fire(events.EventStringAccInput(tx.Input.Address), events.EventDataTx{tx, nil, ""})
+			exe.eventCache.Fire(events.EventStringNameReg(tx.Name), events.EventDataTx{tx, nil, ""})
 		}
 
 		return nil
@@ -713,14 +557,14 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 		// TODO!
 		/*
 			case *txs.BondTx:
-						valInfo := blockCache.State().GetValidatorInfo(tx.PubKey.Address())
+						valInfo := exe.blockCache.State().GetValidatorInfo(tx.PublicKey().Address())
 						if valInfo != nil {
 							// TODO: In the future, check that the validator wasn't destroyed,
 							// add funds, merge UnbondTo outputs, and unbond validator.
 							return errors.New("Adding coins to existing validators not yet supported")
 						}
 
-						accounts, err := getInputs(blockCache, tx.Inputs)
+						accounts, err := getInputs(exe.blockCache, tx.Inputs)
 						if err != nil {
 							return err
 						}
@@ -728,29 +572,29 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 						// add outputs to accounts map
 						// if any outputs don't exist, all inputs must have CreateAccount perm
 						// though outputs aren't created until unbonding/release time
-						canCreate := hasCreateAccountPermission(blockCache, accounts)
+						canCreate := hasCreateAccountPermission(exe.blockCache, accounts)
 						for _, out := range tx.UnbondTo {
-							acc := blockCache.GetAccount(out.Address)
+							acc := exe.blockCache.GetAccount(out.Address)
 							if acc == nil && !canCreate {
 								return fmt.Errorf("At least one input does not have permission to create accounts")
 							}
 						}
 
-						bondAcc := blockCache.GetAccount(tx.PubKey.Address())
-						if !hasBondPermission(blockCache, bondAcc) {
+						bondAcc := exe.blockCache.GetAccount(tx.PublicKey().Address())
+						if !hasBondPermission(exe.blockCache, bondAcc) {
 							return fmt.Errorf("The bonder does not have permission to bond")
 						}
 
-						if !hasBondOrSendPermission(blockCache, accounts) {
+						if !hasBondOrSendPermission(exe.blockCache, accounts) {
 							return fmt.Errorf("At least one input lacks permission to bond")
 						}
 
-						signBytes := acm.SignBytes(_s.ChainID, tx)
+						signBytes := acm.SignBytes(exe.chainID, tx)
 						inTotal, err := validateInputs(accounts, signBytes, tx.Inputs)
 						if err != nil {
 							return err
 						}
-						if !tx.PubKey.VerifyBytes(signBytes, tx.Signature) {
+						if !tx.PublicKey().VerifyBytes(signBytes, tx.Signature) {
 							return txs.ErrTxInvalidSignature
 						}
 						outTotal, err := validateOutputs(tx.UnbondTo)
@@ -766,30 +610,30 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 						// Good! Adjust accounts
 						adjustByInputs(accounts, tx.Inputs)
 						for _, acc := range accounts {
-							blockCache.UpdateAccount(acc)
+							exe.blockCache.UpdateAccount(acc)
 						}
 						// Add ValidatorInfo
 						_s.SetValidatorInfo(&txs.ValidatorInfo{
-							Address:         tx.PubKey.Address(),
-							PubKey:          tx.PubKey,
+							Address:         tx.PublicKey().Address(),
+							PublicKey:          tx.PublicKey(),
 							UnbondTo:        tx.UnbondTo,
-							FirstBondHeight: _s.LastBlockHeight + 1,
+							FirstBondHeight: _s.lastBlockHeight + 1,
 							FirstBondAmount: outTotal,
 						})
 						// Add Validator
 						added := _s.BondedValidators.Add(&txs.Validator{
-							Address:     tx.PubKey.Address(),
-							PubKey:      tx.PubKey,
-							BondHeight:  _s.LastBlockHeight + 1,
+							Address:     tx.PublicKey().Address(),
+							PublicKey:      tx.PublicKey(),
+							BondHeight:  _s.lastBlockHeight + 1,
 							VotingPower: outTotal,
 							Accum:       0,
 						})
 						if !added {
 							PanicCrisis("Failed to add validator")
 						}
-						if evc != nil {
+						if exe.eventCache != nil {
 							// TODO: fire for all inputs
-							evc.FireEvent(txs.EventStringBond(), txs.EventDataTx{tx, nil, ""})
+							exe.eventCache.Fire(txs.EventStringBond(), txs.EventDataTx{tx, nil, ""})
 						}
 						return nil
 
@@ -801,8 +645,8 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 						}
 
 						// Verify the signature
-						signBytes := acm.SignBytes(_s.ChainID, tx)
-						if !val.PubKey.VerifyBytes(signBytes, tx.Signature) {
+						signBytes := acm.SignBytes(exe.chainID, tx)
+						if !val.PublicKey().VerifyBytes(signBytes, tx.Signature) {
 							return txs.ErrTxInvalidSignature
 						}
 
@@ -813,8 +657,8 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 
 						// Good!
 						_s.unbondValidator(val)
-						if evc != nil {
-							evc.FireEvent(txs.EventStringUnbond(), txs.EventDataTx{tx, nil, ""})
+						if exe.eventCache != nil {
+							exe.eventCache.Fire(txs.EventStringUnbond(), txs.EventDataTx{tx, nil, ""})
 						}
 						return nil
 
@@ -826,14 +670,14 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 						}
 
 						// Verify the signature
-						signBytes := acm.SignBytes(_s.ChainID, tx)
-						if !val.PubKey.VerifyBytes(signBytes, tx.Signature) {
+						signBytes := acm.SignBytes(exe.chainID, tx)
+						if !val.PublicKey().VerifyBytes(signBytes, tx.Signature) {
 							return txs.ErrTxInvalidSignature
 						}
 
 						// tx.Height must be in a suitable range
-						minRebondHeight := _s.LastBlockHeight - (validatorTimeoutBlocks / 2)
-						maxRebondHeight := _s.LastBlockHeight + 2
+						minRebondHeight := _s.lastBlockHeight - (validatorTimeoutBlocks / 2)
+						maxRebondHeight := _s.lastBlockHeight + 2
 						if !((minRebondHeight <= tx.Height) && (tx.Height <= maxRebondHeight)) {
 							return errors.New(Fmt("Rebond height not in range.  Expected %v <= %v <= %v",
 								minRebondHeight, tx.Height, maxRebondHeight))
@@ -841,66 +685,30 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 
 						// Good!
 						_s.rebondValidator(val)
-						if evc != nil {
-							evc.FireEvent(txs.EventStringRebond(), txs.EventDataTx{tx, nil, ""})
+						if exe.eventCache != nil {
+							exe.eventCache.Fire(txs.EventStringRebond(), txs.EventDataTx{tx, nil, ""})
 						}
 						return nil
 
-					case *txs.DupeoutTx:
-						// Verify the signatures
-						_, accused := _s.BondedValidators.GetByAddress(tx.Address)
-						if accused == nil {
-							_, accused = _s.UnbondingValidators.GetByAddress(tx.Address)
-							if accused == nil {
-								return txs.ErrTxInvalidAddress
-							}
-						}
-						voteASignBytes := acm.SignBytes(_s.ChainID, &tx.VoteA)
-						voteBSignBytes := acm.SignBytes(_s.ChainID, &tx.VoteB)
-						if !accused.PubKey.VerifyBytes(voteASignBytes, tx.VoteA.Signature) ||
-							!accused.PubKey.VerifyBytes(voteBSignBytes, tx.VoteB.Signature) {
-							return txs.ErrTxInvalidSignature
-						}
-
-						// Verify equivocation
-						// TODO: in the future, just require one vote from a previous height that
-						// doesn't exist on this chain.
-						if tx.VoteA.Height != tx.VoteB.Height {
-							return errors.New("DupeoutTx heights don't match")
-						}
-						if tx.VoteA.Round != tx.VoteB.Round {
-							return errors.New("DupeoutTx rounds don't match")
-						}
-						if tx.VoteA.Type != tx.VoteB.Type {
-							return errors.New("DupeoutTx types don't match")
-						}
-						if bytes.Equal(tx.VoteA.BlockHash, tx.VoteB.BlockHash) {
-							return errors.New("DupeoutTx blockhashes shouldn't match")
-						}
-
-						// Good! (Bad validator!)
-						_s.destroyValidator(accused)
-						if evc != nil {
-							evc.FireEvent(txs.EventStringDupeout(), txs.EventDataTx{tx, nil, ""})
-						}
-						return nil
 		*/
 
 	case *txs.PermissionsTx:
-		var inAcc *acm.Account
-
 		// Validate input
-		inAcc = blockCache.GetAccount(tx.Input.Address)
+		inAcc, err := acm.GetMutableAccount(exe.blockCache, tx.Input.Address)
+		if err != nil {
+			return err
+		}
 		if inAcc == nil {
 			logging.InfoMsg(logger, "Cannot find input account",
 				"tx_input", tx.Input)
 			return txs.ErrTxInvalidAddress
 		}
 
-		permFlag := tx.PermArgs.PermFlag()
+		permFlag := tx.PermArgs.PermFlag
 		// check permission
-		if !HasPermission(blockCache, inAcc, permFlag, logger) {
-			return fmt.Errorf("Account %X does not have moderator permission %s (%b)", tx.Input.Address, ptypes.PermFlagToString(permFlag), permFlag)
+		if !HasPermission(exe.blockCache, inAcc, permFlag, logger) {
+			return fmt.Errorf("account %s does not have moderator permission %s (%b)", tx.Input.Address,
+				permission.PermFlagToString(permFlag), permFlag)
 		}
 
 		// pubKey should be present in either "inAcc" or "tx.Input"
@@ -909,8 +717,8 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 				"tx_input", tx.Input)
 			return err
 		}
-		signBytes := acm.SignBytes(_s.ChainID, tx)
-		err := validateInput(inAcc, signBytes, tx.Input)
+		signBytes := acm.SignBytes(exe.chainID, tx)
+		err = validateInput(inAcc, signBytes, tx.Input)
 		if err != nil {
 			logging.InfoMsg(logger, "validateInput failed",
 				"tx_input", tx.Input,
@@ -921,47 +729,49 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 		value := tx.Input.Amount
 
 		logging.TraceMsg(logger, "New PermissionsTx",
-			"perm_flag", ptypes.PermFlagToString(permFlag),
+			"perm_flag", permission.PermFlagToString(permFlag),
 			"perm_args", tx.PermArgs)
 
-		var permAcc *acm.Account
-		switch args := tx.PermArgs.(type) {
-		case *ptypes.HasBaseArgs:
+		var permAcc acm.Account
+		switch tx.PermArgs.PermFlag {
+		case permission.HasBase:
 			// this one doesn't make sense from txs
 			return fmt.Errorf("HasBase is for contracts, not humans. Just look at the blockchain")
-		case *ptypes.SetBaseArgs:
-			if permAcc = blockCache.GetAccount(args.Address); permAcc == nil {
-				return fmt.Errorf("Trying to update permissions for unknown account %X", args.Address)
-			}
-			err = permAcc.Permissions.Base.Set(args.Permission, args.Value)
-		case *ptypes.UnsetBaseArgs:
-			if permAcc = blockCache.GetAccount(args.Address); permAcc == nil {
-				return fmt.Errorf("Trying to update permissions for unknown account %X", args.Address)
-			}
-			err = permAcc.Permissions.Base.Unset(args.Permission)
-		case *ptypes.SetGlobalArgs:
-			if permAcc = blockCache.GetAccount(ptypes.GlobalPermissionsAddress); permAcc == nil {
-				sanity.PanicSanity("can't find global permissions account")
-			}
-			err = permAcc.Permissions.Base.Set(args.Permission, args.Value)
-		case *ptypes.HasRoleArgs:
+		case permission.SetBase:
+			permAcc, err = mutatePermissions(exe.blockCache, tx.PermArgs.Address,
+				func(perms *ptypes.AccountPermissions) error {
+					return perms.Base.Set(tx.PermArgs.Permission, tx.PermArgs.Value)
+				})
+		case permission.UnsetBase:
+			permAcc, err = mutatePermissions(exe.blockCache, tx.PermArgs.Address,
+				func(perms *ptypes.AccountPermissions) error {
+					return perms.Base.Unset(tx.PermArgs.Permission)
+				})
+		case permission.SetGlobal:
+			permAcc, err = mutatePermissions(exe.blockCache, permission.GlobalPermissionsAddress,
+				func(perms *ptypes.AccountPermissions) error {
+					return perms.Base.Set(tx.PermArgs.Permission, tx.PermArgs.Value)
+				})
+		case permission.HasRole:
 			return fmt.Errorf("HasRole is for contracts, not humans. Just look at the blockchain")
-		case *ptypes.AddRoleArgs:
-			if permAcc = blockCache.GetAccount(args.Address); permAcc == nil {
-				return fmt.Errorf("Trying to update roles for unknown account %X", args.Address)
-			}
-			if !permAcc.Permissions.AddRole(args.Role) {
-				return fmt.Errorf("Role (%s) already exists for account %X", args.Role, args.Address)
-			}
-		case *ptypes.RmRoleArgs:
-			if permAcc = blockCache.GetAccount(args.Address); permAcc == nil {
-				return fmt.Errorf("Trying to update roles for unknown account %X", args.Address)
-			}
-			if !permAcc.Permissions.RmRole(args.Role) {
-				return fmt.Errorf("Role (%s) does not exist for account %X", args.Role, args.Address)
-			}
+		case permission.AddRole:
+			permAcc, err = mutatePermissions(exe.blockCache, tx.PermArgs.Address,
+				func(perms *ptypes.AccountPermissions) error {
+					if !perms.AddRole(tx.PermArgs.Role) {
+						return fmt.Errorf("role (%s) already exists for account %s", tx.PermArgs.Role, tx.PermArgs.Address)
+					}
+					return nil
+				})
+		case permission.RemoveRole:
+			permAcc, err = mutatePermissions(exe.blockCache, tx.PermArgs.Address,
+				func(perms *ptypes.AccountPermissions) error {
+					if !perms.RmRole(tx.PermArgs.Role) {
+						return fmt.Errorf("role (%s) does not exist for account %s", tx.PermArgs.Role, tx.PermArgs.Address)
+					}
+					return nil
+				})
 		default:
-			sanity.PanicSanity(fmt.Sprintf("invalid permission function: %s", ptypes.PermFlagToString(permFlag)))
+			panic(fmt.Sprintf("invalid permission function: %s", permission.PermFlagToString(permFlag)))
 		}
 
 		// TODO: maybe we want to take funds on error and allow txs in that don't do anythingi?
@@ -970,34 +780,345 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 		}
 
 		// Good!
-		inAcc.Sequence += 1
-		inAcc.Balance -= value
-		blockCache.UpdateAccount(inAcc)
+		inAcc.IncSequence()
+		inAcc.SubtractFromBalance(value)
+		exe.blockCache.UpdateAccount(inAcc)
 		if permAcc != nil {
-			blockCache.UpdateAccount(permAcc)
+			exe.blockCache.UpdateAccount(permAcc)
 		}
 
-		if evc != nil {
-			evc.FireEvent(txs.EventStringAccInput(tx.Input.Address), txs.EventDataTx{tx, nil, ""})
-			evc.FireEvent(txs.EventStringPermissions(ptypes.PermFlagToString(permFlag)), txs.EventDataTx{tx, nil, ""})
+		if exe.eventCache != nil {
+			exe.eventCache.Fire(events.EventStringAccInput(tx.Input.Address),
+				events.EventDataTx{tx, nil, ""})
+			exe.eventCache.Fire(events.EventStringPermissions(permission.PermFlagToString(permFlag)),
+				events.EventDataTx{tx, nil, ""})
 		}
 
 		return nil
 
 	default:
 		// binary decoding should not let this happen
-		sanity.PanicSanity("Unknown Tx type")
+		panic("Unknown Tx type")
 		return nil
 	}
 }
 
+func mutatePermissions(stateReader acm.StateReader, address acm.Address,
+	mutator func(*ptypes.AccountPermissions) error) (acm.Account, error) {
+
+	account, err := stateReader.GetAccount(address)
+	if err != nil {
+		return nil, err
+	}
+	if account == nil {
+		return nil, fmt.Errorf("could not get account at address %s in order to alter permissions", address)
+	}
+	mutableAccount := acm.AsMutableAccount(account)
+
+	return mutableAccount, mutator(mutableAccount.MutablePermissions())
+}
+
+// ExecBlock stuff is now taken care of by the consensus engine.
+// But we leave here for now for reference when we have to do validator updates
+
+/*
+
+// NOTE: If an error occurs during block execution, state will be left
+// at an invalid state.  Copy the state before calling ExecBlock!
+func ExecBlock(s *State, block *txs.Block, blockPartsHeader txs.PartSetHeader) error {
+	err := execBlock(s, block, blockPartsHeader)
+	if err != nil {
+		return err
+	}
+	// State.Hash should match block.StateHash
+	stateHash := s.Hash()
+	if !bytes.Equal(stateHash, block.StateHash) {
+		return errors.New(Fmt("Invalid state hash. Expected %X, got %X",
+			stateHash, block.StateHash))
+	}
+	return nil
+}
+
+// executes transactions of a block, does not check block.StateHash
+// NOTE: If an error occurs during block execution, state will be left
+// at an invalid state.  Copy the state before calling execBlock!
+func execBlock(s *State, block *txs.Block, blockPartsHeader txs.PartSetHeader) error {
+	// Basic block validation.
+	err := block.ValidateBasic(s.chainID, s.lastBlockHeight, s.lastBlockAppHash, s.LastBlockParts, s.lastBlockTime)
+	if err != nil {
+		return err
+	}
+
+	// Validate block LastValidation.
+	if block.Height == 1 {
+		if len(block.LastValidation.Precommits) != 0 {
+			return errors.New("Block at height 1 (first block) should have no LastValidation precommits")
+		}
+	} else {
+		if len(block.LastValidation.Precommits) != s.LastBondedValidators.Size() {
+			return errors.New(Fmt("Invalid block validation size. Expected %v, got %v",
+				s.LastBondedValidators.Size(), len(block.LastValidation.Precommits)))
+		}
+		err := s.LastBondedValidators.VerifyValidation(
+			s.chainID, s.lastBlockAppHash, s.LastBlockParts, block.Height-1, block.LastValidation)
+		if err != nil {
+			return err
+		}
+	}
+
+	// Update Validator.LastCommitHeight as necessary.
+	for i, precommit := range block.LastValidation.Precommits {
+		if precommit == nil {
+			continue
+		}
+		_, val := s.LastBondedValidators.GetByIndex(i)
+		if val == nil {
+			PanicCrisis(Fmt("Failed to fetch validator at index %v", i))
+		}
+		if _, val_ := s.BondedValidators.GetByAddress(val.Address); val_ != nil {
+			val_.LastCommitHeight = block.Height - 1
+			updated := s.BondedValidators.Update(val_)
+			if !updated {
+				PanicCrisis("Failed to update bonded validator LastCommitHeight")
+			}
+		} else if _, val_ := s.UnbondingValidators.GetByAddress(val.Address); val_ != nil {
+			val_.LastCommitHeight = block.Height - 1
+			updated := s.UnbondingValidators.Update(val_)
+			if !updated {
+				PanicCrisis("Failed to update unbonding validator LastCommitHeight")
+			}
+		} else {
+			PanicCrisis("Could not find validator")
+		}
+	}
+
+	// Remember LastBondedValidators
+	s.LastBondedValidators = s.BondedValidators.Copy()
+
+	// Create BlockCache to cache changes to state.
+	blockCache := NewBlockCache(s)
+
+	// Execute each tx
+	for _, tx := range block.Data.Txs {
+		err := ExecTx(blockCache, tx, true, s.eventCache)
+		if err != nil {
+			return InvalidTxError{tx, err}
+		}
+	}
+
+	// Now sync the BlockCache to the backend.
+	blockCache.Sync()
+
+	// If any unbonding periods are over,
+	// reward account with bonded coins.
+	toRelease := []*txs.Validator{}
+	s.UnbondingValidators.Iterate(func(index int, val *txs.Validator) bool {
+		if val.UnbondHeight+unbondingPeriodBlocks < block.Height {
+			toRelease = append(toRelease, val)
+		}
+		return false
+	})
+	for _, val := range toRelease {
+		s.releaseValidator(val)
+	}
+
+	// If any validators haven't signed in a while,
+	// unbond them, they have timed out.
+	toTimeout := []*txs.Validator{}
+	s.BondedValidators.Iterate(func(index int, val *txs.Validator) bool {
+		lastActivityHeight := MaxInt(val.BondHeight, val.LastCommitHeight)
+		if lastActivityHeight+validatorTimeoutBlocks < block.Height {
+			log.Notice("Validator timeout", "validator", val, "height", block.Height)
+			toTimeout = append(toTimeout, val)
+		}
+		return false
+	})
+	for _, val := range toTimeout {
+		s.unbondValidator(val)
+	}
+
+	// Increment validator AccumPowers
+	s.BondedValidators.IncrementAccum(1)
+	s.lastBlockHeight = block.Height
+	s.lastBlockAppHash = block.Hash()
+	s.LastBlockParts = blockPartsHeader
+	s.lastBlockTime = block.Time
+	return nil
+}
+*/
+
+// The accounts from the TxInputs must either already have
+// 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,
+	ins []*txs.TxInput) (map[acm.Address]acm.MutableAccount, error) {
+
+	accounts := map[acm.Address]acm.MutableAccount{}
+	for _, in := range ins {
+		// Account shouldn't be duplicated
+		if _, ok := accounts[in.Address]; ok {
+			return nil, txs.ErrTxDuplicateAddress
+		}
+		acc, err := acm.GetMutableAccount(accountGetter, in.Address)
+		if err != nil {
+			return nil, err
+		}
+		if acc == nil {
+			return nil, txs.ErrTxInvalidAddress
+		}
+		// PublicKey should be present in either "account" or "in"
+		if err := checkInputPubKey(acc, in); err != nil {
+			return nil, err
+		}
+		accounts[in.Address] = acc
+	}
+	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) {
+	if accs == nil {
+		accs = make(map[acm.Address]acm.MutableAccount)
+	}
+
+	// we should err if an account is being created but the inputs don't have permission
+	var checkedCreatePerms bool
+	for _, out := range outs {
+		// Account shouldn't be duplicated
+		if _, ok := accs[out.Address]; ok {
+			return nil, txs.ErrTxDuplicateAddress
+		}
+		acc, err := acm.GetMutableAccount(accountGetter, out.Address)
+		if err != nil {
+			return nil, err
+		}
+		// output account may be nil (new)
+		if acc == nil {
+			if !checkedCreatePerms {
+				if !hasCreateAccountPermission(accountGetter, accs, logger) {
+					return nil, fmt.Errorf("at least one input does not have permission to create accounts")
+				}
+				checkedCreatePerms = true
+			}
+			acc = acm.ConcreteAccount{
+				Address:     out.Address,
+				Sequence:    0,
+				Balance:     0,
+				Permissions: permission.ZeroAccountPermissions,
+			}.MutableAccount()
+		}
+		accs[out.Address] = acc
+	}
+	return accs, nil
+}
+
+// Since all ethereum accounts implicitly exist we sometimes lazily create an Account object to represent them
+// only when needed. Sometimes we need to create an unknown Account knowing only its address (which is expected to
+// be a deterministic hash of its associated public key) and not its public key. When we eventually receive a
+// transaction acting on behalf of that account we will be given a public key that we can check matches the address.
+// If it does then we will associate the public key with the stub account already registered in the system once and
+// for all time.
+func checkInputPubKey(acc acm.MutableAccount, in *txs.TxInput) error {
+	if acc.PublicKey().Unwrap() == nil {
+		if in.PubKey.Unwrap() == nil {
+			return txs.ErrTxUnknownPubKey
+		}
+		addressFromPubKey := in.PubKey.Address()
+		addressFromAccount := acc.Address()
+		if addressFromPubKey != addressFromAccount {
+			return txs.ErrTxInvalidPubKey
+		}
+		acc.SetPublicKey(in.PubKey)
+	} else {
+		in.PubKey = acm.PublicKey{}
+	}
+	return nil
+}
+
+func validateInputs(accs map[acm.Address]acm.MutableAccount, signBytes []byte, ins []*txs.TxInput) (total uint64, err error) {
+	for _, in := range ins {
+		acc := accs[in.Address]
+		if acc == nil {
+			panic("validateInputs() expects account in accounts")
+		}
+		err = validateInput(acc, signBytes, in)
+		if err != nil {
+			return
+		}
+		// Good. Add amount to total
+		total += in.Amount
+	}
+	return total, nil
+}
+
+func validateInput(acc acm.MutableAccount, signBytes []byte, in *txs.TxInput) (err error) {
+	// Check TxInput basic
+	if err := in.ValidateBasic(); err != nil {
+		return err
+	}
+	// Check signatures
+	if !acc.PublicKey().VerifyBytes(signBytes, in.Signature) {
+		return txs.ErrTxInvalidSignature
+	}
+	// Check sequences
+	if acc.Sequence()+1 != uint64(in.Sequence) {
+		return txs.ErrTxInvalidSequence{
+			Got:      in.Sequence,
+			Expected: acc.Sequence() + uint64(1),
+		}
+	}
+	// Check amount
+	if acc.Balance() < uint64(in.Amount) {
+		return txs.ErrTxInsufficientFunds
+	}
+	return nil
+}
+
+func validateOutputs(outs []*txs.TxOutput) (total uint64, err error) {
+	for _, out := range outs {
+		// Check TxOutput basic
+		if err := out.ValidateBasic(); err != nil {
+			return 0, err
+		}
+		// Good. Add amount to total
+		total += out.Amount
+	}
+	return total, nil
+}
+
+func adjustByInputs(accs map[acm.Address]acm.MutableAccount, ins []*txs.TxInput) {
+	for _, in := range ins {
+		acc := accs[in.Address]
+		if acc == nil {
+			panic("adjustByInputs() expects account in accounts")
+		}
+		if acc.Balance() < in.Amount {
+			panic("adjustByInputs() expects sufficient funds")
+		}
+		acc.SubtractFromBalance(in.Amount)
+
+		acc.IncSequence()
+	}
+}
+
+func adjustByOutputs(accs map[acm.Address]acm.MutableAccount, outs []*txs.TxOutput) {
+	for _, out := range outs {
+		acc := accs[out.Address]
+		if acc == nil {
+			panic("adjustByOutputs() expects account in accounts")
+		}
+		acc.AddToBalance(out.Amount)
+	}
+}
+
 //---------------------------------------------------------------
 
 // Get permission on an account or fall back to global value
-func HasPermission(state AccountGetter, acc *acm.Account, perm ptypes.PermFlag,
+func HasPermission(accountGetter acm.Getter, acc acm.Account, perm ptypes.PermFlag,
 	logger logging_types.InfoTraceLogger) bool {
-	if perm > ptypes.AllPermFlags {
-		sanity.PanicSanity("Checking an unknown permission in state should never happen")
+	if perm > permission.AllPermFlags {
+		panic("Checking an unknown permission in state should never happen")
 	}
 
 	//if acc == nil {
@@ -1005,16 +1126,17 @@ func HasPermission(state AccountGetter, acc *acm.Account, perm ptypes.PermFlag,
 	// this needs to fall back to global or do some other specific things
 	// eg. a bondAcc may be nil and so can only bond if global bonding is true
 	//}
-	permString := ptypes.PermFlagToString(perm)
+	permString := permission.PermFlagToString(perm)
 
-	v, err := acc.Permissions.Base.Get(perm)
+	v, err := acc.Permissions().Base.Get(perm)
 	if _, ok := err.(ptypes.ErrValueNotSet); ok {
-		if state == nil {
-			sanity.PanicSanity("All known global permissions should be set!")
+		if accountGetter == nil {
+			panic("All known global permissions should be set!")
 		}
 		logging.TraceMsg(logger, "Permission for account is not set. Querying GlobalPermissionsAddres.",
 			"perm_flag", permString)
-		return HasPermission(nil, state.GetAccount(ptypes.GlobalPermissionsAddress), perm, logger)
+
+		return HasPermission(nil, permission.GlobalPermissionsAccount(accountGetter), perm, logger)
 	} else if v {
 		logging.TraceMsg(logger, "Account has permission",
 			"account_address", acc.Address,
@@ -1028,51 +1150,51 @@ func HasPermission(state AccountGetter, acc *acm.Account, perm ptypes.PermFlag,
 }
 
 // TODO: for debug log the failed accounts
-func hasSendPermission(state AccountGetter, accs map[string]*acm.Account,
+func hasSendPermission(accountGetter acm.Getter, accs map[acm.Address]acm.MutableAccount,
 	logger logging_types.InfoTraceLogger) bool {
 	for _, acc := range accs {
-		if !HasPermission(state, acc, ptypes.Send, logger) {
+		if !HasPermission(accountGetter, acc, permission.Send, logger) {
 			return false
 		}
 	}
 	return true
 }
 
-func hasNamePermission(state AccountGetter, acc *acm.Account,
+func hasNamePermission(accountGetter acm.Getter, acc acm.Account,
 	logger logging_types.InfoTraceLogger) bool {
-	return HasPermission(state, acc, ptypes.Name, logger)
+	return HasPermission(accountGetter, acc, permission.Name, logger)
 }
 
-func hasCallPermission(state AccountGetter, acc *acm.Account,
+func hasCallPermission(accountGetter acm.Getter, acc acm.Account,
 	logger logging_types.InfoTraceLogger) bool {
-	return HasPermission(state, acc, ptypes.Call, logger)
+	return HasPermission(accountGetter, acc, permission.Call, logger)
 }
 
-func hasCreateContractPermission(state AccountGetter, acc *acm.Account,
+func hasCreateContractPermission(accountGetter acm.Getter, acc acm.Account,
 	logger logging_types.InfoTraceLogger) bool {
-	return HasPermission(state, acc, ptypes.CreateContract, logger)
+	return HasPermission(accountGetter, acc, permission.CreateContract, logger)
 }
 
-func hasCreateAccountPermission(state AccountGetter, accs map[string]*acm.Account,
+func hasCreateAccountPermission(accountGetter acm.Getter, accs map[acm.Address]acm.MutableAccount,
 	logger logging_types.InfoTraceLogger) bool {
 	for _, acc := range accs {
-		if !HasPermission(state, acc, ptypes.CreateAccount, logger) {
+		if !HasPermission(accountGetter, acc, permission.CreateAccount, logger) {
 			return false
 		}
 	}
 	return true
 }
 
-func hasBondPermission(state AccountGetter, acc *acm.Account,
+func hasBondPermission(accountGetter acm.Getter, acc acm.Account,
 	logger logging_types.InfoTraceLogger) bool {
-	return HasPermission(state, acc, ptypes.Bond, logger)
+	return HasPermission(accountGetter, acc, permission.Bond, logger)
 }
 
-func hasBondOrSendPermission(state AccountGetter, accs map[string]*acm.Account,
+func hasBondOrSendPermission(accountGetter acm.Getter, accs map[acm.Address]acm.Account,
 	logger logging_types.InfoTraceLogger) bool {
 	for _, acc := range accs {
-		if !HasPermission(state, acc, ptypes.Bond, logger) {
-			if !HasPermission(state, acc, ptypes.Send, logger) {
+		if !HasPermission(accountGetter, acc, permission.Bond, logger) {
+			if !HasPermission(accountGetter, acc, permission.Send, logger) {
 				return false
 			}
 		}
diff --git a/execution/execution_test.go b/execution/execution_test.go
new file mode 100644
index 00000000..68e4d96b
--- /dev/null
+++ b/execution/execution_test.go
@@ -0,0 +1,1329 @@
+// 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 execution
+
+import (
+	"bytes"
+	"fmt"
+	"strconv"
+	"testing"
+	"time"
+
+	acm "github.com/hyperledger/burrow/account"
+	. "github.com/hyperledger/burrow/binary"
+	bcm "github.com/hyperledger/burrow/blockchain"
+	"github.com/hyperledger/burrow/event"
+	exe_events "github.com/hyperledger/burrow/execution/events"
+	"github.com/hyperledger/burrow/execution/evm"
+	. "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/genesis"
+	"github.com/hyperledger/burrow/logging/loggers"
+	"github.com/hyperledger/burrow/permission"
+	ptypes "github.com/hyperledger/burrow/permission/types"
+	"github.com/hyperledger/burrow/txs"
+	dbm "github.com/tendermint/tmlibs/db"
+)
+
+var (
+	dbBackend           = "memdb"
+	dbDir               = ""
+	permissionsContract = evm.SNativeContracts()["Permissions"]
+)
+
+/*
+Permission Tests:
+
+- SendTx:
+x	- 1 input, no perm, call perm, create perm
+x	- 1 input, perm
+x	- 2 inputs, one with perm one without
+
+- CallTx, CALL
+x	- 1 input, no perm, send perm, create perm
+x	- 1 input, perm
+x	- contract runs call but doesn't have call perm
+x	- contract runs call and has call perm
+x	- contract runs call (with perm), runs contract that runs call (without perm)
+x	- contract runs call (with perm), runs contract that runs call (with perm)
+
+- CallTx for Create, CREATE
+x	- 1 input, no perm, send perm, call perm
+x 	- 1 input, perm
+x	- contract runs create but doesn't have create perm
+x	- contract runs create but has perm
+x	- contract runs call with empty address (has call and create perm)
+
+- NameTx
+	- no perm, send perm, call perm
+	- with perm
+
+- BondTx
+x	- 1 input, no perm
+x	- 1 input, perm
+x	- 1 bonder with perm, input without send or bond
+x	- 1 bonder with perm, input with send
+x	- 1 bonder with perm, input with bond
+x	- 2 inputs, one with perm one without
+
+- SendTx for new account
+x 	- 1 input, 1 unknown ouput, input with send, not create  (fail)
+x 	- 1 input, 1 unknown ouput, input with send and create (pass)
+x 	- 2 inputs, 1 unknown ouput, both inputs with send, one with create, one without (fail)
+x 	- 2 inputs, 1 known output, 1 unknown ouput, one input with create, one without (fail)
+x 	- 2 inputs, 1 unknown ouput, both inputs with send, both inputs with create (pass )
+x 	- 2 inputs, 1 known output, 1 unknown ouput, both inputs with create, (pass)
+
+
+- CALL for new account
+x	- unknown output, without create (fail)
+x	- unknown output, with create (pass)
+
+
+- SNative (CallTx, CALL):
+	- for each of CallTx, Call
+x		- call each snative without permission, fails
+x		- call each snative with permission, pass
+	- list:
+x		- base: has,set,unset
+x		- globals: set
+x 		- roles: has, add, rm
+
+
+*/
+
+// keys
+var users = makeUsers(10)
+var logger = loggers.NewNoopInfoTraceLogger()
+
+func makeUsers(n int) []acm.PrivateAccount {
+	users := make([]acm.PrivateAccount, n)
+	for i := 0; i < n; i++ {
+		secret := "mysecret" + strconv.Itoa(i)
+		users[i] = acm.GeneratePrivateAccountFromSecret(secret)
+	}
+	return users
+}
+
+func makeExecutor(state *State) *executor {
+	return newExecutor(true, state, testChainID, bcm.NewBlockchain(testGenesisDoc), event.NewEmitter(logger),
+		logger)
+}
+
+func newBaseGenDoc(globalPerm, accountPerm ptypes.AccountPermissions) genesis.GenesisDoc {
+	genAccounts := []genesis.Account{}
+	for _, user := range users[:5] {
+		accountPermCopy := accountPerm // Create new instance for custom overridability.
+		genAccounts = append(genAccounts, genesis.Account{
+			BasicAccount: genesis.BasicAccount{
+				Address: user.Address(),
+				Amount:  1000000,
+			},
+			Permissions: accountPermCopy,
+		})
+	}
+
+	return genesis.GenesisDoc{
+		GenesisTime:       time.Now(),
+		ChainName:         testGenesisDoc.ChainName,
+		GlobalPermissions: globalPerm,
+		Accounts:          genAccounts,
+		Validators: []genesis.Validator{
+			{
+				BasicAccount: genesis.BasicAccount{
+					PublicKey: users[0].PublicKey(),
+					Amount:    10,
+				},
+				UnbondTo: []genesis.BasicAccount{
+					{
+						Address: users[0].Address(),
+					},
+				},
+			},
+		},
+	}
+}
+
+//func getAccount(state acm.Getter, address acm.Address) acm.MutableAccount {
+//	acc, _ := acm.GetMutableAccount(state, address)
+//	return acc
+//}
+
+func TestSendFails(t *testing.T) {
+	stateDB := dbm.NewDB("state", dbBackend, dbDir)
+	genDoc := newBaseGenDoc(permission.ZeroAccountPermissions, permission.ZeroAccountPermissions)
+	genDoc.Accounts[1].Permissions.Base.Set(permission.Send, true)
+	genDoc.Accounts[2].Permissions.Base.Set(permission.Call, true)
+	genDoc.Accounts[3].Permissions.Base.Set(permission.CreateContract, true)
+	st := MakeGenesisState(stateDB, &genDoc)
+	batchCommitter := makeExecutor(st)
+
+	//-------------------
+	// send txs
+
+	// simple send tx should fail
+	tx := txs.NewSendTx()
+	if err := tx.AddInput(batchCommitter.blockCache, users[0].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(users[1].Address(), 5)
+	tx.SignInput(testChainID, 0, users[0])
+	if err := batchCommitter.Execute(tx); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// simple send tx with call perm should fail
+	tx = txs.NewSendTx()
+	if err := tx.AddInput(batchCommitter.blockCache, users[2].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(users[4].Address(), 5)
+	tx.SignInput(testChainID, 0, users[2])
+	if err := batchCommitter.Execute(tx); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// simple send tx with create perm should fail
+	tx = txs.NewSendTx()
+	if err := tx.AddInput(batchCommitter.blockCache, users[3].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(users[4].Address(), 5)
+	tx.SignInput(testChainID, 0, users[3])
+	if err := batchCommitter.Execute(tx); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// simple send tx to unknown account without create_account perm should fail
+	acc := getAccount(batchCommitter.blockCache, users[3].Address())
+	acc.MutablePermissions().Base.Set(permission.Send, true)
+	batchCommitter.blockCache.UpdateAccount(acc)
+	tx = txs.NewSendTx()
+	if err := tx.AddInput(batchCommitter.blockCache, users[3].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(users[6].Address(), 5)
+	tx.SignInput(testChainID, 0, users[3])
+	if err := batchCommitter.Execute(tx); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+}
+
+func TestName(t *testing.T) {
+	stateDB := dbm.NewDB("state", dbBackend, dbDir)
+	genDoc := newBaseGenDoc(permission.ZeroAccountPermissions, permission.ZeroAccountPermissions)
+	genDoc.Accounts[0].Permissions.Base.Set(permission.Send, true)
+	genDoc.Accounts[1].Permissions.Base.Set(permission.Name, true)
+	st := MakeGenesisState(stateDB, &genDoc)
+	batchCommitter := makeExecutor(st)
+
+	//-------------------
+	// name txs
+
+	// simple name tx without perm should fail
+	tx, err := txs.NewNameTx(st, users[0].PublicKey(), "somename", "somedata", 10000, 100)
+	if err != nil {
+		t.Fatal(err)
+	}
+	tx.Sign(testChainID, users[0])
+	if err := batchCommitter.Execute(tx); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// simple name tx with perm should pass
+	tx, err = txs.NewNameTx(st, users[1].PublicKey(), "somename", "somedata", 10000, 100)
+	if err != nil {
+		t.Fatal(err)
+	}
+	tx.Sign(testChainID, users[1])
+	if err := batchCommitter.Execute(tx); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestCallFails(t *testing.T) {
+	stateDB := dbm.NewDB("state", dbBackend, dbDir)
+	genDoc := newBaseGenDoc(permission.ZeroAccountPermissions, permission.ZeroAccountPermissions)
+	genDoc.Accounts[1].Permissions.Base.Set(permission.Send, true)
+	genDoc.Accounts[2].Permissions.Base.Set(permission.Call, true)
+	genDoc.Accounts[3].Permissions.Base.Set(permission.CreateContract, true)
+	st := MakeGenesisState(stateDB, &genDoc)
+	batchCommitter := makeExecutor(st)
+
+	//-------------------
+	// call txs
+
+	address4 := users[4].Address()
+	// simple call tx should fail
+	tx, _ := txs.NewCallTx(batchCommitter.blockCache, users[0].PublicKey(), &address4, nil, 100, 100, 100)
+	tx.Sign(testChainID, users[0])
+	if err := batchCommitter.Execute(tx); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// simple call tx with send permission should fail
+	tx, _ = txs.NewCallTx(batchCommitter.blockCache, users[1].PublicKey(), &address4, nil, 100, 100, 100)
+	tx.Sign(testChainID, users[1])
+	if err := batchCommitter.Execute(tx); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// simple call tx with create permission should fail
+	tx, _ = txs.NewCallTx(batchCommitter.blockCache, users[3].PublicKey(), &address4, nil, 100, 100, 100)
+	tx.Sign(testChainID, users[3])
+	if err := batchCommitter.Execute(tx); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	//-------------------
+	// create txs
+
+	// simple call create tx should fail
+	tx, _ = txs.NewCallTx(batchCommitter.blockCache, users[0].PublicKey(), nil, nil, 100, 100, 100)
+	tx.Sign(testChainID, users[0])
+	if err := batchCommitter.Execute(tx); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// simple call create tx with send perm should fail
+	tx, _ = txs.NewCallTx(batchCommitter.blockCache, users[1].PublicKey(), nil, nil, 100, 100, 100)
+	tx.Sign(testChainID, users[1])
+	if err := batchCommitter.Execute(tx); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// simple call create tx with call perm should fail
+	tx, _ = txs.NewCallTx(batchCommitter.blockCache, users[2].PublicKey(), nil, nil, 100, 100, 100)
+	tx.Sign(testChainID, users[2])
+	if err := batchCommitter.Execute(tx); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+}
+
+func TestSendPermission(t *testing.T) {
+	stateDB := dbm.NewDB("state", dbBackend, dbDir)
+	genDoc := newBaseGenDoc(permission.ZeroAccountPermissions, permission.ZeroAccountPermissions)
+	genDoc.Accounts[0].Permissions.Base.Set(permission.Send, true) // give the 0 account permission
+	st := MakeGenesisState(stateDB, &genDoc)
+	batchCommitter := makeExecutor(st)
+
+	// A single input, having the permission, should succeed
+	tx := txs.NewSendTx()
+	if err := tx.AddInput(batchCommitter.blockCache, users[0].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(users[1].Address(), 5)
+	tx.SignInput(testChainID, 0, users[0])
+	if err := batchCommitter.Execute(tx); err != nil {
+		t.Fatal("Transaction failed", err)
+	}
+
+	// Two inputs, one with permission, one without, should fail
+	tx = txs.NewSendTx()
+	if err := tx.AddInput(batchCommitter.blockCache, users[0].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	if err := tx.AddInput(batchCommitter.blockCache, users[1].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(users[2].Address(), 10)
+	tx.SignInput(testChainID, 0, users[0])
+	tx.SignInput(testChainID, 1, users[1])
+	if err := batchCommitter.Execute(tx); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+}
+
+func TestCallPermission(t *testing.T) {
+	stateDB := dbm.NewDB("state", dbBackend, dbDir)
+	genDoc := newBaseGenDoc(permission.ZeroAccountPermissions, permission.ZeroAccountPermissions)
+	genDoc.Accounts[0].Permissions.Base.Set(permission.Call, true) // give the 0 account permission
+	st := MakeGenesisState(stateDB, &genDoc)
+	batchCommitter := makeExecutor(st)
+
+	//------------------------------
+	// call to simple contract
+	fmt.Println("\n##### SIMPLE CONTRACT")
+
+	// create simple contract
+	simpleContractAddr := acm.NewContractAddress(users[0].Address(), 100)
+	simpleAcc := acm.ConcreteAccount{
+		Address:     simpleContractAddr,
+		Balance:     0,
+		Code:        []byte{0x60},
+		Sequence:    0,
+		StorageRoot: Zero256.Bytes(),
+		Permissions: permission.ZeroAccountPermissions,
+	}.MutableAccount()
+	st.UpdateAccount(simpleAcc)
+
+	// A single input, having the permission, should succeed
+	tx, _ := txs.NewCallTx(batchCommitter.blockCache, users[0].PublicKey(), &simpleContractAddr, nil, 100, 100, 100)
+	tx.Sign(testChainID, users[0])
+	if err := batchCommitter.Execute(tx); err != nil {
+		t.Fatal("Transaction failed", err)
+	}
+
+	//----------------------------------------------------------
+	// call to contract that calls simple contract - without perm
+	fmt.Println("\n##### CALL TO SIMPLE CONTRACT (FAIL)")
+
+	// create contract that calls the simple contract
+	contractCode := callContractCode(simpleContractAddr)
+	caller1ContractAddr := acm.NewContractAddress(users[0].Address(), 101)
+	caller1Acc := acm.ConcreteAccount{
+		Address:     caller1ContractAddr,
+		Balance:     10000,
+		Code:        contractCode,
+		Sequence:    0,
+		StorageRoot: Zero256.Bytes(),
+		Permissions: permission.ZeroAccountPermissions,
+	}.MutableAccount()
+	batchCommitter.blockCache.UpdateAccount(caller1Acc)
+
+	// A single input, having the permission, but the contract doesn't have permission
+	tx, _ = txs.NewCallTx(batchCommitter.blockCache, users[0].PublicKey(), &caller1ContractAddr, nil, 100, 10000, 100)
+	tx.Sign(testChainID, users[0])
+
+	// we need to subscribe to the Call event to detect the exception
+	_, exception := execTxWaitEvent(t, batchCommitter, tx, evm_events.EventStringAccCall(caller1ContractAddr)) //
+	if exception == "" {
+		t.Fatal("Expected exception")
+	}
+
+	//----------------------------------------------------------
+	// call to contract that calls simple contract - with perm
+	fmt.Println("\n##### CALL TO SIMPLE CONTRACT (PASS)")
+
+	// A single input, having the permission, and the contract has permission
+	caller1Acc.MutablePermissions().Base.Set(permission.Call, true)
+	batchCommitter.blockCache.UpdateAccount(caller1Acc)
+	tx, _ = txs.NewCallTx(batchCommitter.blockCache, users[0].PublicKey(), &caller1ContractAddr, nil, 100, 10000, 100)
+	tx.Sign(testChainID, users[0])
+
+	// we need to subscribe to the Call event to detect the exception
+	_, exception = execTxWaitEvent(t, batchCommitter, tx, evm_events.EventStringAccCall(caller1ContractAddr)) //
+	if exception != "" {
+		t.Fatal("Unexpected exception:", exception)
+	}
+
+	//----------------------------------------------------------
+	// call to contract that calls contract that calls simple contract - without perm
+	// caller1Contract calls simpleContract. caller2Contract calls caller1Contract.
+	// caller1Contract does not have call perms, but caller2Contract does.
+	fmt.Println("\n##### CALL TO CONTRACT CALLING SIMPLE CONTRACT (FAIL)")
+
+	contractCode2 := callContractCode(caller1ContractAddr)
+	caller2ContractAddr := acm.NewContractAddress(users[0].Address(), 102)
+	caller2Acc := acm.ConcreteAccount{
+		Address:     caller2ContractAddr,
+		Balance:     1000,
+		Code:        contractCode2,
+		Sequence:    0,
+		StorageRoot: Zero256.Bytes(),
+		Permissions: permission.ZeroAccountPermissions,
+	}.MutableAccount()
+	caller1Acc.MutablePermissions().Base.Set(permission.Call, false)
+	caller2Acc.MutablePermissions().Base.Set(permission.Call, true)
+	batchCommitter.blockCache.UpdateAccount(caller1Acc)
+	batchCommitter.blockCache.UpdateAccount(caller2Acc)
+
+	tx, _ = txs.NewCallTx(batchCommitter.blockCache, users[0].PublicKey(), &caller2ContractAddr, nil, 100, 10000, 100)
+	tx.Sign(testChainID, users[0])
+
+	// we need to subscribe to the Call event to detect the exception
+	_, exception = execTxWaitEvent(t, batchCommitter, tx, evm_events.EventStringAccCall(caller1ContractAddr)) //
+	if exception == "" {
+		t.Fatal("Expected exception")
+	}
+
+	//----------------------------------------------------------
+	// call to contract that calls contract that calls simple contract - without perm
+	// caller1Contract calls simpleContract. caller2Contract calls caller1Contract.
+	// both caller1 and caller2 have permission
+	fmt.Println("\n##### CALL TO CONTRACT CALLING SIMPLE CONTRACT (PASS)")
+
+	caller1Acc.MutablePermissions().Base.Set(permission.Call, true)
+	batchCommitter.blockCache.UpdateAccount(caller1Acc)
+
+	tx, _ = txs.NewCallTx(batchCommitter.blockCache, users[0].PublicKey(), &caller2ContractAddr, nil, 100, 10000, 100)
+	tx.Sign(testChainID, users[0])
+
+	// we need to subscribe to the Call event to detect the exception
+	_, exception = execTxWaitEvent(t, batchCommitter, tx, evm_events.EventStringAccCall(caller1ContractAddr)) //
+	if exception != "" {
+		t.Fatal("Unexpected exception", exception)
+	}
+}
+
+func TestCreatePermission(t *testing.T) {
+	stateDB := dbm.NewDB("state", dbBackend, dbDir)
+	genDoc := newBaseGenDoc(permission.ZeroAccountPermissions, permission.ZeroAccountPermissions)
+	genDoc.Accounts[0].Permissions.Base.Set(permission.CreateContract, true) // give the 0 account permission
+	genDoc.Accounts[0].Permissions.Base.Set(permission.Call, true)           // give the 0 account permission
+	st := MakeGenesisState(stateDB, &genDoc)
+	batchCommitter := makeExecutor(st)
+
+	//------------------------------
+	// create a simple contract
+	fmt.Println("\n##### CREATE SIMPLE CONTRACT")
+
+	contractCode := []byte{0x60}
+	createCode := wrapContractForCreate(contractCode)
+
+	// A single input, having the permission, should succeed
+	tx, _ := txs.NewCallTx(batchCommitter.blockCache, users[0].PublicKey(), nil, createCode, 100, 100, 100)
+	tx.Sign(testChainID, users[0])
+	if err := batchCommitter.Execute(tx); err != nil {
+		t.Fatal("Transaction failed", err)
+	}
+	// ensure the contract is there
+	contractAddr := acm.NewContractAddress(tx.Input.Address, tx.Input.Sequence)
+	contractAcc := getAccount(batchCommitter.blockCache, contractAddr)
+	if contractAcc == nil {
+		t.Fatalf("failed to create contract %s", contractAddr)
+	}
+	if !bytes.Equal(contractAcc.Code(), contractCode) {
+		t.Fatalf("contract does not have correct code. Got %X, expected %X", contractAcc.Code(), contractCode)
+	}
+
+	//------------------------------
+	// create contract that uses the CREATE op
+	fmt.Println("\n##### CREATE FACTORY")
+
+	contractCode = []byte{0x60}
+	createCode = wrapContractForCreate(contractCode)
+	factoryCode := createContractCode()
+	createFactoryCode := wrapContractForCreate(factoryCode)
+
+	// A single input, having the permission, should succeed
+	tx, _ = txs.NewCallTx(batchCommitter.blockCache, users[0].PublicKey(), nil, createFactoryCode, 100, 100, 100)
+	tx.Sign(testChainID, users[0])
+	if err := batchCommitter.Execute(tx); err != nil {
+		t.Fatal("Transaction failed", err)
+	}
+	// ensure the contract is there
+	contractAddr = acm.NewContractAddress(tx.Input.Address, tx.Input.Sequence)
+	contractAcc = getAccount(batchCommitter.blockCache, contractAddr)
+	if contractAcc == nil {
+		t.Fatalf("failed to create contract %s", contractAddr)
+	}
+	if !bytes.Equal(contractAcc.Code(), factoryCode) {
+		t.Fatalf("contract does not have correct code. Got %X, expected %X", contractAcc.Code(), factoryCode)
+	}
+
+	//------------------------------
+	// call the contract (should FAIL)
+	fmt.Println("\n###### CALL THE FACTORY (FAIL)")
+
+	// A single input, having the permission, should succeed
+	tx, _ = txs.NewCallTx(batchCommitter.blockCache, users[0].PublicKey(), &contractAddr, createCode, 100, 100, 100)
+	tx.Sign(testChainID, users[0])
+	// we need to subscribe to the Call event to detect the exception
+	_, exception := execTxWaitEvent(t, batchCommitter, tx, evm_events.EventStringAccCall(contractAddr)) //
+	if exception == "" {
+		t.Fatal("expected exception")
+	}
+
+	//------------------------------
+	// call the contract (should PASS)
+	fmt.Println("\n###### CALL THE FACTORY (PASS)")
+
+	contractAcc.MutablePermissions().Base.Set(permission.CreateContract, true)
+	batchCommitter.blockCache.UpdateAccount(contractAcc)
+
+	// A single input, having the permission, should succeed
+	tx, _ = txs.NewCallTx(batchCommitter.blockCache, users[0].PublicKey(), &contractAddr, createCode, 100, 100, 100)
+	tx.Sign(testChainID, users[0])
+	// we need to subscribe to the Call event to detect the exception
+	_, exception = execTxWaitEvent(t, batchCommitter, tx, evm_events.EventStringAccCall(contractAddr)) //
+	if exception != "" {
+		t.Fatal("unexpected exception", exception)
+	}
+
+	//--------------------------------
+	fmt.Println("\n##### CALL to empty address")
+	code := callContractCode(acm.Address{})
+
+	contractAddr = acm.NewContractAddress(users[0].Address(), 110)
+	contractAcc = acm.ConcreteAccount{
+		Address:     contractAddr,
+		Balance:     1000,
+		Code:        code,
+		Sequence:    0,
+		StorageRoot: Zero256.Bytes(),
+		Permissions: permission.ZeroAccountPermissions,
+	}.MutableAccount()
+	contractAcc.MutablePermissions().Base.Set(permission.Call, true)
+	contractAcc.MutablePermissions().Base.Set(permission.CreateContract, true)
+	batchCommitter.blockCache.UpdateAccount(contractAcc)
+
+	// this should call the 0 address but not create ...
+	tx, _ = txs.NewCallTx(batchCommitter.blockCache, users[0].PublicKey(), &contractAddr, createCode, 100, 10000, 100)
+	tx.Sign(testChainID, users[0])
+	// we need to subscribe to the Call event to detect the exception
+	_, exception = execTxWaitEvent(t, batchCommitter, tx, evm_events.EventStringAccCall(acm.Address{})) //
+	if exception != "" {
+		t.Fatal("unexpected exception", exception)
+	}
+	zeroAcc := getAccount(batchCommitter.blockCache, acm.Address{})
+	if len(zeroAcc.Code()) != 0 {
+		t.Fatal("the zero account was given code from a CALL!")
+	}
+}
+
+/* TODO
+func TestBondPermission(t *testing.T) {
+	stateDB := dbm.NewDB("state",dbBackend,dbDir)
+	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
+	st := MakeGenesisState(stateDB, &genDoc)
+	batchCommitter := makeExecutor(st)
+	var bondAcc *acm.Account
+
+	//------------------------------
+	// one bonder without permission should fail
+	tx, _ := txs.NewBondTx(users[1].PublicKey())
+	if err := tx.AddInput(batchCommitter.blockCache, users[1].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(users[1].Address(), 5)
+	tx.SignInput(testChainID, 0, users[1])
+	tx.SignBond(testChainID, users[1])
+	if err := ExecTx(batchCommitter.blockCache, tx, true, nil); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	//------------------------------
+	// one bonder with permission should pass
+	bondAcc = batchCommitter.blockCache.GetAccount(users[1].Address())
+	bondAcc.Permissions.Base.Set(permission.Bond, true)
+	batchCommitter.blockCache.UpdateAccount(bondAcc)
+	if err := ExecTx(batchCommitter.blockCache, tx, true, nil); err != nil {
+		t.Fatal("Unexpected error", err)
+	}
+
+	// reset state (we can only bond with an account once ..)
+	genDoc = newBaseGenDoc(PermsAllFalse, PermsAllFalse)
+	st = MakeGenesisState(stateDB, &genDoc)
+	batchCommitter.blockCache = NewBlockCache(st)
+	bondAcc = batchCommitter.blockCache.GetAccount(users[1].Address())
+	bondAcc.Permissions.Base.Set(permission.Bond, true)
+	batchCommitter.blockCache.UpdateAccount(bondAcc)
+	//------------------------------
+	// one bonder with permission and an input without send should fail
+	tx, _ = txs.NewBondTx(users[1].PublicKey())
+	if err := tx.AddInput(batchCommitter.blockCache, users[2].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(users[1].Address(), 5)
+	tx.SignInput(testChainID, 0, users[2])
+	tx.SignBond(testChainID, users[1])
+	if err := ExecTx(batchCommitter.blockCache, tx, true, nil); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// reset state (we can only bond with an account once ..)
+	genDoc = newBaseGenDoc(PermsAllFalse, PermsAllFalse)
+	st = MakeGenesisState(stateDB, &genDoc)
+	batchCommitter.blockCache = NewBlockCache(st)
+	bondAcc = batchCommitter.blockCache.GetAccount(users[1].Address())
+	bondAcc.Permissions.Base.Set(permission.Bond, true)
+	batchCommitter.blockCache.UpdateAccount(bondAcc)
+	//------------------------------
+	// one bonder with permission and an input with send should pass
+	sendAcc := batchCommitter.blockCache.GetAccount(users[2].Address())
+	sendAcc.Permissions.Base.Set(permission.Send, true)
+	batchCommitter.blockCache.UpdateAccount(sendAcc)
+	tx, _ = txs.NewBondTx(users[1].PublicKey())
+	if err := tx.AddInput(batchCommitter.blockCache, users[2].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(users[1].Address(), 5)
+	tx.SignInput(testChainID, 0, users[2])
+	tx.SignBond(testChainID, users[1])
+	if err := ExecTx(batchCommitter.blockCache, tx, true, nil); err != nil {
+		t.Fatal("Unexpected error", err)
+	}
+
+	// reset state (we can only bond with an account once ..)
+	genDoc = newBaseGenDoc(PermsAllFalse, PermsAllFalse)
+	st = MakeGenesisState(stateDB, &genDoc)
+	batchCommitter.blockCache = NewBlockCache(st)
+	bondAcc = batchCommitter.blockCache.GetAccount(users[1].Address())
+	bondAcc.Permissions.Base.Set(permission.Bond, true)
+	batchCommitter.blockCache.UpdateAccount(bondAcc)
+	//------------------------------
+	// one bonder with permission and an input with bond should pass
+	sendAcc.Permissions.Base.Set(permission.Bond, true)
+	batchCommitter.blockCache.UpdateAccount(sendAcc)
+	tx, _ = txs.NewBondTx(users[1].PublicKey())
+	if err := tx.AddInput(batchCommitter.blockCache, users[2].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(users[1].Address(), 5)
+	tx.SignInput(testChainID, 0, users[2])
+	tx.SignBond(testChainID, users[1])
+	if err := ExecTx(batchCommitter.blockCache, tx, true, nil); err != nil {
+		t.Fatal("Unexpected error", err)
+	}
+
+	// reset state (we can only bond with an account once ..)
+	genDoc = newBaseGenDoc(PermsAllFalse, PermsAllFalse)
+	st = MakeGenesisState(stateDB, &genDoc)
+	batchCommitter.blockCache = NewBlockCache(st)
+	bondAcc = batchCommitter.blockCache.GetAccount(users[1].Address())
+	bondAcc.Permissions.Base.Set(permission.Bond, true)
+	batchCommitter.blockCache.UpdateAccount(bondAcc)
+	//------------------------------
+	// one bonder with permission and an input from that bonder and an input without send or bond should fail
+	tx, _ = txs.NewBondTx(users[1].PublicKey())
+	if err := tx.AddInput(batchCommitter.blockCache, users[1].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	if err := tx.AddInput(batchCommitter.blockCache, users[2].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(users[1].Address(), 5)
+	tx.SignInput(testChainID, 0, users[1])
+	tx.SignInput(testChainID, 1, users[2])
+	tx.SignBond(testChainID, users[1])
+	if err := ExecTx(batchCommitter.blockCache, tx, true, nil); err == nil {
+		t.Fatal("Expected error")
+	}
+}
+*/
+
+func TestCreateAccountPermission(t *testing.T) {
+	stateDB := dbm.NewDB("state", dbBackend, dbDir)
+	genDoc := newBaseGenDoc(permission.ZeroAccountPermissions, permission.ZeroAccountPermissions)
+	genDoc.Accounts[0].Permissions.Base.Set(permission.Send, true)          // give the 0 account permission
+	genDoc.Accounts[1].Permissions.Base.Set(permission.Send, true)          // give the 0 account permission
+	genDoc.Accounts[0].Permissions.Base.Set(permission.CreateAccount, true) // give the 0 account permission
+	st := MakeGenesisState(stateDB, &genDoc)
+	batchCommitter := makeExecutor(st)
+
+	//----------------------------------------------------------
+	// SendTx to unknown account
+
+	// A single input, having the permission, should succeed
+	tx := txs.NewSendTx()
+	if err := tx.AddInput(batchCommitter.blockCache, users[0].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(users[6].Address(), 5)
+	tx.SignInput(testChainID, 0, users[0])
+	if err := batchCommitter.Execute(tx); err != nil {
+		t.Fatal("Transaction failed", err)
+	}
+
+	// Two inputs, both with send, one with create, one without, should fail
+	tx = txs.NewSendTx()
+	if err := tx.AddInput(batchCommitter.blockCache, users[0].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	if err := tx.AddInput(batchCommitter.blockCache, users[1].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(users[7].Address(), 10)
+	tx.SignInput(testChainID, 0, users[0])
+	tx.SignInput(testChainID, 1, users[1])
+	if err := batchCommitter.Execute(tx); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// Two inputs, both with send, one with create, one without, two ouputs (one known, one unknown) should fail
+	tx = txs.NewSendTx()
+	if err := tx.AddInput(batchCommitter.blockCache, users[0].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	if err := tx.AddInput(batchCommitter.blockCache, users[1].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(users[7].Address(), 4)
+	tx.AddOutput(users[4].Address(), 6)
+	tx.SignInput(testChainID, 0, users[0])
+	tx.SignInput(testChainID, 1, users[1])
+	if err := batchCommitter.Execute(tx); err == nil {
+		t.Fatal("Expected error")
+	} else {
+		fmt.Println(err)
+	}
+
+	// Two inputs, both with send, both with create, should pass
+	acc := getAccount(batchCommitter.blockCache, users[1].Address())
+	acc.MutablePermissions().Base.Set(permission.CreateAccount, true)
+	batchCommitter.blockCache.UpdateAccount(acc)
+	tx = txs.NewSendTx()
+	if err := tx.AddInput(batchCommitter.blockCache, users[0].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	if err := tx.AddInput(batchCommitter.blockCache, users[1].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(users[7].Address(), 10)
+	tx.SignInput(testChainID, 0, users[0])
+	tx.SignInput(testChainID, 1, users[1])
+	if err := batchCommitter.Execute(tx); err != nil {
+		t.Fatal("Unexpected error", err)
+	}
+
+	// Two inputs, both with send, both with create, two outputs (one known, one unknown) should pass
+	tx = txs.NewSendTx()
+	if err := tx.AddInput(batchCommitter.blockCache, users[0].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	if err := tx.AddInput(batchCommitter.blockCache, users[1].PublicKey(), 5); err != nil {
+		t.Fatal(err)
+	}
+	tx.AddOutput(users[7].Address(), 7)
+	tx.AddOutput(users[4].Address(), 3)
+	tx.SignInput(testChainID, 0, users[0])
+	tx.SignInput(testChainID, 1, users[1])
+	if err := batchCommitter.Execute(tx); err != nil {
+		t.Fatal("Unexpected error", err)
+	}
+
+	//----------------------------------------------------------
+	// CALL to unknown account
+
+	acc = getAccount(batchCommitter.blockCache, users[0].Address())
+	acc.MutablePermissions().Base.Set(permission.Call, true)
+	batchCommitter.blockCache.UpdateAccount(acc)
+
+	// call to contract that calls unknown account - without create_account perm
+	// create contract that calls the simple contract
+	contractCode := callContractCode(users[9].Address())
+	caller1ContractAddr := acm.NewContractAddress(users[4].Address(), 101)
+	caller1Acc := acm.ConcreteAccount{
+		Address:     caller1ContractAddr,
+		Balance:     0,
+		Code:        contractCode,
+		Sequence:    0,
+		StorageRoot: Zero256.Bytes(),
+		Permissions: permission.ZeroAccountPermissions,
+	}.MutableAccount()
+	batchCommitter.blockCache.UpdateAccount(caller1Acc)
+
+	// A single input, having the permission, but the contract doesn't have permission
+	txCall, _ := txs.NewCallTx(batchCommitter.blockCache, users[0].PublicKey(), &caller1ContractAddr, nil, 100, 10000, 100)
+	txCall.Sign(testChainID, users[0])
+
+	// we need to subscribe to the Call event to detect the exception
+	_, exception := execTxWaitEvent(t, batchCommitter, txCall, evm_events.EventStringAccCall(caller1ContractAddr)) //
+	if exception == "" {
+		t.Fatal("Expected exception")
+	}
+
+	// NOTE: for a contract to be able to CreateAccount, it must be able to call
+	// NOTE: for a users to be able to CreateAccount, it must be able to send!
+	caller1Acc.MutablePermissions().Base.Set(permission.CreateAccount, true)
+	caller1Acc.MutablePermissions().Base.Set(permission.Call, true)
+	batchCommitter.blockCache.UpdateAccount(caller1Acc)
+	// A single input, having the permission, but the contract doesn't have permission
+	txCall, _ = txs.NewCallTx(batchCommitter.blockCache, users[0].PublicKey(), &caller1ContractAddr, nil, 100, 10000, 100)
+	txCall.Sign(testChainID, users[0])
+
+	// we need to subscribe to the Call event to detect the exception
+	_, exception = execTxWaitEvent(t, batchCommitter, txCall, evm_events.EventStringAccCall(caller1ContractAddr)) //
+	if exception != "" {
+		t.Fatal("Unexpected exception", exception)
+	}
+
+}
+
+// holla at my boy
+var DougAddress acm.Address
+
+func init() {
+	copy(DougAddress[:], ([]byte)("THISISDOUG"))
+}
+
+func TestSNativeCALL(t *testing.T) {
+	stateDB := dbm.NewDB("state", dbBackend, dbDir)
+	genDoc := newBaseGenDoc(permission.ZeroAccountPermissions, permission.ZeroAccountPermissions)
+	genDoc.Accounts[0].Permissions.Base.Set(permission.Call, true) // give the 0 account permission
+	genDoc.Accounts[3].Permissions.Base.Set(permission.Bond, true) // some arbitrary permission to play with
+	genDoc.Accounts[3].Permissions.AddRole("bumble")
+	genDoc.Accounts[3].Permissions.AddRole("bee")
+	st := MakeGenesisState(stateDB, &genDoc)
+	batchCommitter := makeExecutor(st)
+
+	//----------------------------------------------------------
+	// Test CALL to SNative contracts
+
+	// make the main contract once
+	doug := acm.ConcreteAccount{
+		Address:     DougAddress,
+		Balance:     0,
+		Code:        nil,
+		Sequence:    0,
+		StorageRoot: Zero256.Bytes(),
+		Permissions: permission.ZeroAccountPermissions,
+	}.MutableAccount()
+
+	doug.MutablePermissions().Base.Set(permission.Call, true)
+	//doug.Permissions.Base.Set(permission.HasBase, true)
+	batchCommitter.blockCache.UpdateAccount(doug)
+
+	fmt.Println("\n#### HasBase")
+	// HasBase
+	snativeAddress, pF, data := snativePermTestInputCALL("hasBase", users[3], permission.Bond, false)
+	testSNativeCALLExpectFail(t, batchCommitter, doug, snativeAddress, data)
+	testSNativeCALLExpectPass(t, batchCommitter, doug, pF, snativeAddress, data, func(ret []byte) error {
+		// return value should be true or false as a 32 byte array...
+		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
+			return fmt.Errorf("Expected 1. Got %X", ret)
+		}
+		return nil
+	})
+
+	fmt.Println("\n#### SetBase")
+	// SetBase
+	snativeAddress, pF, data = snativePermTestInputCALL("setBase", users[3], permission.Bond, false)
+	testSNativeCALLExpectFail(t, batchCommitter, doug, snativeAddress, data)
+	testSNativeCALLExpectPass(t, batchCommitter, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, pF, data = snativePermTestInputCALL("hasBase", users[3], permission.Bond, false)
+	testSNativeCALLExpectPass(t, batchCommitter, doug, pF, snativeAddress, data, func(ret []byte) error {
+		// return value should be true or false as a 32 byte array...
+		if !IsZeros(ret) {
+			return fmt.Errorf("Expected 0. Got %X", ret)
+		}
+		return nil
+	})
+	snativeAddress, pF, data = snativePermTestInputCALL("setBase", users[3], permission.CreateContract, true)
+	testSNativeCALLExpectPass(t, batchCommitter, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, pF, data = snativePermTestInputCALL("hasBase", users[3], permission.CreateContract, false)
+	testSNativeCALLExpectPass(t, batchCommitter, doug, pF, snativeAddress, data, func(ret []byte) error {
+		// return value should be true or false as a 32 byte array...
+		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
+			return fmt.Errorf("Expected 1. Got %X", ret)
+		}
+		return nil
+	})
+
+	fmt.Println("\n#### UnsetBase")
+	// UnsetBase
+	snativeAddress, pF, data = snativePermTestInputCALL("unsetBase", users[3], permission.CreateContract, false)
+	testSNativeCALLExpectFail(t, batchCommitter, doug, snativeAddress, data)
+	testSNativeCALLExpectPass(t, batchCommitter, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, pF, data = snativePermTestInputCALL("hasBase", users[3], permission.CreateContract, false)
+	testSNativeCALLExpectPass(t, batchCommitter, doug, pF, snativeAddress, data, func(ret []byte) error {
+		if !IsZeros(ret) {
+			return fmt.Errorf("Expected 0. Got %X", ret)
+		}
+		return nil
+	})
+
+	fmt.Println("\n#### SetGlobal")
+	// SetGlobalPerm
+	snativeAddress, pF, data = snativePermTestInputCALL("setGlobal", users[3], permission.CreateContract, true)
+	testSNativeCALLExpectFail(t, batchCommitter, doug, snativeAddress, data)
+	testSNativeCALLExpectPass(t, batchCommitter, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, pF, data = snativePermTestInputCALL("hasBase", users[3], permission.CreateContract, false)
+	testSNativeCALLExpectPass(t, batchCommitter, doug, pF, snativeAddress, data, func(ret []byte) error {
+		// return value should be true or false as a 32 byte array...
+		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
+			return fmt.Errorf("Expected 1. Got %X", ret)
+		}
+		return nil
+	})
+
+	fmt.Println("\n#### HasRole")
+	// HasRole
+	snativeAddress, pF, data = snativeRoleTestInputCALL("hasRole", users[3], "bumble")
+	testSNativeCALLExpectFail(t, batchCommitter, doug, snativeAddress, data)
+	testSNativeCALLExpectPass(t, batchCommitter, doug, pF, snativeAddress, data, func(ret []byte) error {
+		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
+			return fmt.Errorf("Expected 1. Got %X", ret)
+		}
+		return nil
+	})
+
+	fmt.Println("\n#### AddRole")
+	// AddRole
+	snativeAddress, pF, data = snativeRoleTestInputCALL("hasRole", users[3], "chuck")
+	testSNativeCALLExpectPass(t, batchCommitter, doug, pF, snativeAddress, data, func(ret []byte) error {
+		if !IsZeros(ret) {
+			return fmt.Errorf("Expected 0. Got %X", ret)
+		}
+		return nil
+	})
+	snativeAddress, pF, data = snativeRoleTestInputCALL("addRole", users[3], "chuck")
+	testSNativeCALLExpectFail(t, batchCommitter, doug, snativeAddress, data)
+	testSNativeCALLExpectPass(t, batchCommitter, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, pF, data = snativeRoleTestInputCALL("hasRole", users[3], "chuck")
+	testSNativeCALLExpectPass(t, batchCommitter, doug, pF, snativeAddress, data, func(ret []byte) error {
+		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
+			return fmt.Errorf("Expected 1. Got %X", ret)
+		}
+		return nil
+	})
+
+	fmt.Println("\n#### RemoveRole")
+	// RemoveRole
+	snativeAddress, pF, data = snativeRoleTestInputCALL("removeRole", users[3], "chuck")
+	testSNativeCALLExpectFail(t, batchCommitter, doug, snativeAddress, data)
+	testSNativeCALLExpectPass(t, batchCommitter, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, pF, data = snativeRoleTestInputCALL("hasRole", users[3], "chuck")
+	testSNativeCALLExpectPass(t, batchCommitter, doug, pF, snativeAddress, data, func(ret []byte) error {
+		if !IsZeros(ret) {
+			return fmt.Errorf("Expected 0. Got %X", ret)
+		}
+		return nil
+	})
+}
+
+func TestSNativeTx(t *testing.T) {
+	stateDB := dbm.NewDB("state", dbBackend, dbDir)
+	genDoc := newBaseGenDoc(permission.ZeroAccountPermissions, permission.ZeroAccountPermissions)
+	genDoc.Accounts[0].Permissions.Base.Set(permission.Call, true) // give the 0 account permission
+	genDoc.Accounts[3].Permissions.Base.Set(permission.Bond, true) // some arbitrary permission to play with
+	genDoc.Accounts[3].Permissions.AddRole("bumble")
+	genDoc.Accounts[3].Permissions.AddRole("bee")
+	st := MakeGenesisState(stateDB, &genDoc)
+	batchCommitter := makeExecutor(st)
+
+	//----------------------------------------------------------
+	// Test SNativeTx
+
+	fmt.Println("\n#### SetBase")
+	// SetBase
+	snativeArgs := snativePermTestInputTx("setBase", users[3], permission.Bond, false)
+	testSNativeTxExpectFail(t, batchCommitter, snativeArgs)
+	testSNativeTxExpectPass(t, batchCommitter, permission.SetBase, snativeArgs)
+	acc := getAccount(batchCommitter.blockCache, users[3].Address())
+	if v, _ := acc.MutablePermissions().Base.Get(permission.Bond); v {
+		t.Fatal("expected permission to be set false")
+	}
+	snativeArgs = snativePermTestInputTx("setBase", users[3], permission.CreateContract, true)
+	testSNativeTxExpectPass(t, batchCommitter, permission.SetBase, snativeArgs)
+	acc = getAccount(batchCommitter.blockCache, users[3].Address())
+	if v, _ := acc.MutablePermissions().Base.Get(permission.CreateContract); !v {
+		t.Fatal("expected permission to be set true")
+	}
+
+	fmt.Println("\n#### UnsetBase")
+	// UnsetBase
+	snativeArgs = snativePermTestInputTx("unsetBase", users[3], permission.CreateContract, false)
+	testSNativeTxExpectFail(t, batchCommitter, snativeArgs)
+	testSNativeTxExpectPass(t, batchCommitter, permission.UnsetBase, snativeArgs)
+	acc = getAccount(batchCommitter.blockCache, users[3].Address())
+	if v, _ := acc.MutablePermissions().Base.Get(permission.CreateContract); v {
+		t.Fatal("expected permission to be set false")
+	}
+
+	fmt.Println("\n#### SetGlobal")
+	// SetGlobalPerm
+	snativeArgs = snativePermTestInputTx("setGlobal", users[3], permission.CreateContract, true)
+	testSNativeTxExpectFail(t, batchCommitter, snativeArgs)
+	testSNativeTxExpectPass(t, batchCommitter, permission.SetGlobal, snativeArgs)
+	acc = getAccount(batchCommitter.blockCache, permission.GlobalPermissionsAddress)
+	if v, _ := acc.MutablePermissions().Base.Get(permission.CreateContract); !v {
+		t.Fatal("expected permission to be set true")
+	}
+
+	fmt.Println("\n#### AddRole")
+	// AddRole
+	snativeArgs = snativeRoleTestInputTx("addRole", users[3], "chuck")
+	testSNativeTxExpectFail(t, batchCommitter, snativeArgs)
+	testSNativeTxExpectPass(t, batchCommitter, permission.AddRole, snativeArgs)
+	acc = getAccount(batchCommitter.blockCache, users[3].Address())
+	if v := acc.Permissions().HasRole("chuck"); !v {
+		t.Fatal("expected role to be added")
+	}
+
+	fmt.Println("\n#### RemoveRole")
+	// RemoveRole
+	snativeArgs = snativeRoleTestInputTx("removeRole", users[3], "chuck")
+	testSNativeTxExpectFail(t, batchCommitter, snativeArgs)
+	testSNativeTxExpectPass(t, batchCommitter, permission.RemoveRole, snativeArgs)
+	acc = getAccount(batchCommitter.blockCache, users[3].Address())
+	if v := acc.Permissions().HasRole("chuck"); v {
+		t.Fatal("expected role to be removed")
+	}
+}
+
+//-------------------------------------------------------------------------------------
+// helpers
+
+var ExceptionTimeOut = "timed out waiting for event"
+
+// run ExecTx and wait for the Call event on given addr
+// returns the msg data and an error/exception
+func execTxWaitEvent(t *testing.T, batchCommitter *executor, tx txs.Tx, eventid string) (interface{}, string) {
+	evsw := event.NewEmitter(logger)
+	ch := make(chan event.AnyEventData)
+	evsw.Subscribe("test", eventid, func(msg event.AnyEventData) {
+		ch <- msg
+	})
+	evc := event.NewEventCache(evsw)
+	batchCommitter.eventCache = evc
+	go func() {
+		if err := batchCommitter.Execute(tx); err != nil {
+			errStr := err.Error()
+			ch <- event.AnyEventData{Err: &errStr}
+		}
+		evc.Flush()
+	}()
+	ticker := time.NewTicker(5 * time.Second)
+	var msg event.AnyEventData
+	select {
+	case msg = <-ch:
+	case <-ticker.C:
+		return nil, ExceptionTimeOut
+	}
+
+	switch ev := msg.Get().(type) {
+	case exe_events.EventDataTx:
+		return ev, ev.Exception
+	case evm_events.EventDataCall:
+		return ev, ev.Exception
+	case string:
+		return nil, ev
+	default:
+		return ev, ""
+	}
+}
+
+// give a contract perms for an snative, call it, it calls the snative, but shouldn't have permission
+func testSNativeCALLExpectFail(t *testing.T, batchCommitter *executor, doug acm.MutableAccount,
+	snativeAddress acm.Address, data []byte) {
+	testSNativeCALL(t, false, batchCommitter, doug, 0, snativeAddress, data, nil)
+}
+
+// give a contract perms for an snative, call it, it calls the snative, ensure the check funciton (f) succeeds
+func testSNativeCALLExpectPass(t *testing.T, batchCommitter *executor, doug acm.MutableAccount, snativePerm ptypes.PermFlag,
+	snativeAddress acm.Address, data []byte, f func([]byte) error) {
+	testSNativeCALL(t, true, batchCommitter, doug, snativePerm, snativeAddress, data, f)
+}
+
+func testSNativeCALL(t *testing.T, expectPass bool, batchCommitter *executor, doug acm.MutableAccount,
+	snativePerm ptypes.PermFlag, snativeAddress acm.Address, data []byte, f func([]byte) error) {
+	if expectPass {
+		doug.MutablePermissions().Base.Set(snativePerm, true)
+	}
+
+	doug.SetCode(callContractCode(snativeAddress))
+	dougAddress := doug.Address()
+
+	batchCommitter.blockCache.UpdateAccount(doug)
+	tx, _ := txs.NewCallTx(batchCommitter.blockCache, users[0].PublicKey(), &dougAddress, data, 100, 10000, 100)
+	tx.Sign(testChainID, users[0])
+	fmt.Println("subscribing to", evm_events.EventStringAccCall(snativeAddress))
+	ev, exception := execTxWaitEvent(t, batchCommitter, tx, evm_events.EventStringAccCall(snativeAddress))
+	if exception == ExceptionTimeOut {
+		t.Fatal("Timed out waiting for event")
+	}
+	if expectPass {
+		if exception != "" {
+			t.Fatal("Unexpected exception", exception)
+		}
+		evv := ev.(evm_events.EventDataCall)
+		ret := evv.Return
+		if err := f(ret); err != nil {
+			t.Fatal(err)
+		}
+	} else {
+		if exception == "" {
+			t.Fatal("Expected exception")
+		}
+	}
+}
+
+func testSNativeTxExpectFail(t *testing.T, batchCommitter *executor, snativeArgs permission.PermArgs) {
+	testSNativeTx(t, false, batchCommitter, 0, snativeArgs)
+}
+
+func testSNativeTxExpectPass(t *testing.T, batchCommitter *executor, perm ptypes.PermFlag, snativeArgs permission.PermArgs) {
+	testSNativeTx(t, true, batchCommitter, perm, snativeArgs)
+}
+
+func testSNativeTx(t *testing.T, expectPass bool, batchCommitter *executor, perm ptypes.PermFlag, snativeArgs permission.PermArgs) {
+	if expectPass {
+		acc := getAccount(batchCommitter.blockCache, users[0].Address())
+		acc.MutablePermissions().Base.Set(perm, true)
+		batchCommitter.blockCache.UpdateAccount(acc)
+	}
+	tx, _ := txs.NewPermissionsTx(batchCommitter.blockCache, users[0].PublicKey(), &snativeArgs)
+	tx.Sign(testChainID, users[0])
+	err := batchCommitter.Execute(tx)
+	if expectPass {
+		if err != nil {
+			t.Fatal("Unexpected exception", err)
+		}
+	} else {
+		if err == nil {
+			t.Fatal("Expected exception")
+		}
+	}
+}
+
+func boolToWord256(v bool) Word256 {
+	var vint byte
+	if v {
+		vint = 0x1
+	} else {
+		vint = 0x0
+	}
+	return LeftPadWord256([]byte{vint})
+}
+
+func permNameToFuncID(name string) []byte {
+	function, err := permissionsContract.FunctionByName(name)
+	if err != nil {
+		panic("didn't find snative function signature!")
+	}
+	id := function.ID()
+	return id[:]
+}
+
+func snativePermTestInputCALL(name string, user acm.PrivateAccount, perm ptypes.PermFlag,
+	val bool) (addr acm.Address, pF ptypes.PermFlag, data []byte) {
+	addr = permissionsContract.Address()
+	switch name {
+	case "hasBase", "unsetBase":
+		data = user.Address().Word256().Bytes()
+		data = append(data, Uint64ToWord256(uint64(perm)).Bytes()...)
+	case "setBase":
+		data = user.Address().Word256().Bytes()
+		data = append(data, Uint64ToWord256(uint64(perm)).Bytes()...)
+		data = append(data, boolToWord256(val).Bytes()...)
+	case "setGlobal":
+		data = Uint64ToWord256(uint64(perm)).Bytes()
+		data = append(data, boolToWord256(val).Bytes()...)
+	}
+	data = append(permNameToFuncID(name), data...)
+	var err error
+	if pF, err = permission.PermStringToFlag(name); err != nil {
+		panic(fmt.Sprintf("failed to convert perm string (%s) to flag", name))
+	}
+	return
+}
+
+func snativePermTestInputTx(name string, user acm.PrivateAccount, perm ptypes.PermFlag, val bool) (snativeArgs permission.PermArgs) {
+	switch name {
+	case "hasBase":
+		snativeArgs = *permission.HasBaseArgs(user.Address(), perm)
+	case "unsetBase":
+		snativeArgs = *permission.UnsetBaseArgs(user.Address(), perm)
+	case "setBase":
+		snativeArgs = *permission.SetBaseArgs(user.Address(), perm, val)
+	case "setGlobal":
+		snativeArgs = *permission.SetGlobalArgs(perm, val)
+	}
+	return
+}
+
+func snativeRoleTestInputCALL(name string, user acm.PrivateAccount,
+	role string) (addr acm.Address, pF ptypes.PermFlag, data []byte) {
+	addr = permissionsContract.Address()
+	data = user.Address().Word256().Bytes()
+	data = append(data, RightPadBytes([]byte(role), 32)...)
+	data = append(permNameToFuncID(name), data...)
+
+	var err error
+	if pF, err = permission.PermStringToFlag(name); err != nil {
+		panic(fmt.Sprintf("failed to convert perm string (%s) to flag", name))
+	}
+	return
+}
+
+func snativeRoleTestInputTx(name string, user acm.PrivateAccount, role string) (snativeArgs permission.PermArgs) {
+	switch name {
+	case "hasRole":
+		snativeArgs = *permission.HasRoleArgs(user.Address(), role)
+	case "addRole":
+		snativeArgs = *permission.AddRoleArgs(user.Address(), role)
+	case "removeRole":
+		snativeArgs = *permission.RemoveRoleArgs(user.Address(), role)
+	}
+	return
+}
+
+// convenience function for contract that calls a given address
+func callContractCode(contractAddr acm.Address) []byte {
+	// calldatacopy into mem and use as input to call
+	memOff, inputOff := byte(0x0), byte(0x0)
+	value := byte(0x1)
+	inOff := byte(0x0)
+	retOff, retSize := byte(0x0), byte(0x20)
+
+	// this is the code we want to run (call a contract and return)
+	return bc.Splice(CALLDATASIZE, PUSH1, inputOff, PUSH1, memOff,
+		CALLDATACOPY, PUSH1, retSize, PUSH1, retOff, CALLDATASIZE, PUSH1, inOff,
+		PUSH1, value, PUSH20, contractAddr,
+		// Zeno loves us - call with half of the available gas each time we CALL
+		PUSH1, 2, GAS, DIV, CALL,
+		PUSH1, 32, PUSH1, 0, RETURN)
+}
+
+// convenience function for contract that is a factory for the code that comes as call data
+func createContractCode() []byte {
+	// TODO: gas ...
+
+	// calldatacopy the calldatasize
+	memOff, inputOff := byte(0x0), byte(0x0)
+	contractCode := []byte{0x60, memOff, 0x60, inputOff, 0x36, 0x37}
+
+	// create
+	value := byte(0x1)
+	contractCode = append(contractCode, []byte{0x60, value, 0x36, 0x60, memOff, 0xf0}...)
+	return contractCode
+}
+
+// wrap a contract in create code
+func wrapContractForCreate(contractCode []byte) []byte {
+	// the is the code we need to return the contractCode when the contract is initialized
+	lenCode := len(contractCode)
+	// push code to the stack
+	code := append([]byte{0x7f}, RightPadWord256(contractCode).Bytes()...)
+	// store it in memory
+	code = append(code, []byte{0x60, 0x0, 0x52}...)
+	// return whats in memory
+	code = append(code, []byte{0x60, byte(lenCode), 0x60, 0x0, 0xf3}...)
+	// return init code, contract code, expected return
+	return code
+}
diff --git a/manager/burrow-mint/namereg.go b/execution/namereg.go
similarity index 63%
rename from manager/burrow-mint/namereg.go
rename to execution/namereg.go
index 3deedd44..5e71f0fc 100644
--- a/manager/burrow-mint/namereg.go
+++ b/execution/namereg.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package burrowmint
+package execution
 
 import (
 	"bytes"
@@ -20,82 +20,108 @@ import (
 	"fmt"
 	"sync"
 
-	sm "github.com/hyperledger/burrow/manager/burrow-mint/state"
-
-	core_types "github.com/hyperledger/burrow/core/types"
-	event "github.com/hyperledger/burrow/event"
+	"github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/blockchain"
+	"github.com/hyperledger/burrow/event"
 )
 
 // NameReg is part of the pipe for BurrowMint and provides the implementation
 // for the pipe to call into the BurrowMint application
 
+type NameRegGetter interface {
+	GetNameRegEntry(name string) *NameRegEntry
+}
+
+type NameRegIterable interface {
+	NameRegGetter
+	IterateNameRegEntries(consumer func(*NameRegEntry) (stop bool)) (stopped bool)
+}
+
 type namereg struct {
-	burrowMint    *BurrowMint
+	state         *State
+	blockchain    blockchain.Blockchain
 	filterFactory *event.FilterFactory
 }
 
-func newNameReg(burrowMint *BurrowMint) *namereg {
+var _ NameRegIterable = &namereg{}
+
+type NameRegEntry struct {
+	Name    string          `json:"name"`    // registered name for the entry
+	Owner   account.Address `json:"owner"`   // address that created the entry
+	Data    string          `json:"data"`    // data to store under this name
+	Expires uint64          `json:"expires"` // block at which this entry expires
+}
 
-	ff := event.NewFilterFactory()
+func NewNameReg(state *State, blockchain blockchain.Blockchain) *namereg {
+	filterFactory := event.NewFilterFactory()
 
-	ff.RegisterFilterPool("name", &sync.Pool{
+	filterFactory.RegisterFilterPool("name", &sync.Pool{
 		New: func() interface{} {
 			return &NameRegNameFilter{}
 		},
 	})
 
-	ff.RegisterFilterPool("owner", &sync.Pool{
+	filterFactory.RegisterFilterPool("owner", &sync.Pool{
 		New: func() interface{} {
 			return &NameRegOwnerFilter{}
 		},
 	})
 
-	ff.RegisterFilterPool("data", &sync.Pool{
+	filterFactory.RegisterFilterPool("data", &sync.Pool{
 		New: func() interface{} {
 			return &NameRegDataFilter{}
 		},
 	})
 
-	ff.RegisterFilterPool("expires", &sync.Pool{
+	filterFactory.RegisterFilterPool("expires", &sync.Pool{
 		New: func() interface{} {
 			return &NameRegExpiresFilter{}
 		},
 	})
 
-	return &namereg{burrowMint, ff}
+	return &namereg{
+		state:         state,
+		blockchain:    blockchain,
+		filterFactory: filterFactory,
+	}
+}
+
+func (nr *namereg) GetNameRegEntry(name string) *NameRegEntry {
+	return nr.state.GetNameRegEntry(name)
+}
+
+func (nr *namereg) IterateNameRegEntries(consumer func(*NameRegEntry) (stop bool)) bool {
+	return nr.state.IterateNameRegEntries(consumer)
 }
 
-func (this *namereg) Entry(key string) (*core_types.NameRegEntry, error) {
-	st := this.burrowMint.GetState() // performs a copy
-	entry := st.GetNameRegEntry(key)
+func (nr *namereg) Entry(key string) (*NameRegEntry, error) {
+	entry := nr.state.GetNameRegEntry(key)
 	if entry == nil {
-		return nil, fmt.Errorf("Entry %s not found", key)
+		return nil, fmt.Errorf("entry %s not found", key)
 	}
 	return entry, nil
 }
 
-func (this *namereg) Entries(filters []*event.FilterData) (*core_types.ResultListNames, error) {
-	var blockHeight int
-	var names []*core_types.NameRegEntry
-	state := this.burrowMint.GetState()
-	blockHeight = state.LastBlockHeight
-	filter, err := this.filterFactory.NewFilter(filters)
+func (nr *namereg) Entries(filters []*event.FilterData) (*ResultListNames, error) {
+	var names []*NameRegEntry
+	blockHeight := nr.blockchain.Tip().LastBlockHeight()
+	filter, err := nr.filterFactory.NewFilter(filters)
 	if err != nil {
 		return nil, fmt.Errorf("Error in query: " + err.Error())
 	}
-	state.GetNames().Iterate(func(key, value []byte) bool {
-		nre := sm.DecodeNameRegEntry(value)
+	nr.state.GetNames().Iterate(func(key, value []byte) bool {
+		nre := DecodeNameRegEntry(value)
 		if filter.Match(nre) {
 			names = append(names, nre)
 		}
 		return false
 	})
-	return &core_types.ResultListNames{blockHeight, names}, nil
+	return &ResultListNames{blockHeight, names}, nil
 }
 
 type ResultListNames struct {
-	BlockHeight int                        `json:"block_height"`
-	Names       []*core_types.NameRegEntry `json:"names"`
+	BlockHeight uint64          `json:"block_height"`
+	Names       []*NameRegEntry `json:"names"`
 }
 
 // Filter for namereg name. This should not be used to get individual entries by name.
@@ -127,7 +153,7 @@ func (this *NameRegNameFilter) Configure(fd *event.FilterData) error {
 }
 
 func (this *NameRegNameFilter) Match(v interface{}) bool {
-	nre, ok := v.(*core_types.NameRegEntry)
+	nre, ok := v.(*NameRegEntry)
 	if !ok {
 		return false
 	}
@@ -147,7 +173,7 @@ func (this *NameRegOwnerFilter) Configure(fd *event.FilterData) error {
 	val, err := hex.DecodeString(fd.Value)
 
 	if err != nil {
-		return fmt.Errorf("Wrong value type.")
+		return fmt.Errorf("wrong value type.")
 	}
 	if op == "==" {
 		this.match = func(a, b []byte) bool {
@@ -166,11 +192,11 @@ func (this *NameRegOwnerFilter) Configure(fd *event.FilterData) error {
 }
 
 func (this *NameRegOwnerFilter) Match(v interface{}) bool {
-	nre, ok := v.(*core_types.NameRegEntry)
+	nre, ok := v.(*NameRegEntry)
 	if !ok {
 		return false
 	}
-	return this.match(nre.Owner, this.value)
+	return this.match(nre.Owner.Bytes(), this.value)
 }
 
 // Filter for namereg data. Useful for example if you store an ipfs hash and know the hash but need the key.
@@ -202,7 +228,7 @@ func (this *NameRegDataFilter) Configure(fd *event.FilterData) error {
 }
 
 func (this *NameRegDataFilter) Match(v interface{}) bool {
-	nre, ok := v.(*core_types.NameRegEntry)
+	nre, ok := v.(*NameRegEntry)
 	if !ok {
 		return false
 	}
@@ -213,8 +239,8 @@ func (this *NameRegDataFilter) Match(v interface{}) bool {
 // Ops: All
 type NameRegExpiresFilter struct {
 	op    string
-	value int64
-	match func(int64, int64) bool
+	value uint64
+	match func(uint64, uint64) bool
 }
 
 func (this *NameRegExpiresFilter) Configure(fd *event.FilterData) error {
@@ -233,9 +259,9 @@ func (this *NameRegExpiresFilter) Configure(fd *event.FilterData) error {
 }
 
 func (this *NameRegExpiresFilter) Match(v interface{}) bool {
-	nre, ok := v.(*core_types.NameRegEntry)
+	nre, ok := v.(*NameRegEntry)
 	if !ok {
 		return false
 	}
-	return this.match(int64(nre.Expires), this.value)
+	return this.match(nre.Expires, this.value)
 }
diff --git a/manager/burrow-mint/state/state.go b/execution/state.go
similarity index 54%
rename from manager/burrow-mint/state/state.go
rename to execution/state.go
index ccf68bf3..74a1b1eb 100644
--- a/manager/burrow-mint/state/state.go
+++ b/execution/state.go
@@ -12,28 +12,26 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package state
+package execution
 
 import (
 	"bytes"
 	"fmt"
 	"io"
-	"io/ioutil"
+	"sync"
 	"time"
 
 	acm "github.com/hyperledger/burrow/account"
-	genesis "github.com/hyperledger/burrow/genesis"
-	ptypes "github.com/hyperledger/burrow/permission/types"
+	"github.com/hyperledger/burrow/binary"
+	"github.com/hyperledger/burrow/genesis"
+	"github.com/hyperledger/burrow/permission"
+	ptypes "github.com/hyperledger/burrow/permission"
 	"github.com/hyperledger/burrow/txs"
-
-	dbm "github.com/tendermint/go-db"
-	"github.com/tendermint/go-events"
-	"github.com/tendermint/go-merkle"
-	"github.com/tendermint/go-wire"
-
-	core_types "github.com/hyperledger/burrow/core/types"
 	"github.com/hyperledger/burrow/util"
-	"github.com/tendermint/tendermint/types"
+	"github.com/tendermint/go-wire"
+	"github.com/tendermint/merkleeyes/iavl"
+	dbm "github.com/tendermint/tmlibs/db"
+	"github.com/tendermint/tmlibs/merkle"
 )
 
 var (
@@ -45,189 +43,240 @@ var (
 	maxLoadStateElementSize      = 0                  // no max
 )
 
+// TODO
+const GasLimit = uint64(1000000)
+
 //-----------------------------------------------------------------------------
 
 // NOTE: not goroutine-safe.
 type State struct {
-	DB              dbm.DB
-	ChainID         string
-	LastBlockHeight int
-	LastBlockHash   []byte
-	LastBlockParts  types.PartSetHeader
-	LastBlockTime   time.Time
+	sync.RWMutex
+	db dbm.DB
 	//	BondedValidators     *types.ValidatorSet
 	//	LastBondedValidators *types.ValidatorSet
 	//	UnbondingValidators  *types.ValidatorSet
 	accounts       merkle.Tree // Shouldn't be accessed directly.
 	validatorInfos merkle.Tree // Shouldn't be accessed directly.
 	nameReg        merkle.Tree // Shouldn't be accessed directly.
+}
+
+// Implements account and blockchain state
+var _ acm.Updater = &State{}
+
+var _ acm.StateIterable = &State{}
+
+var _ acm.StateWriter = &State{}
+
+func MakeGenesisState(db dbm.DB, genDoc *genesis.GenesisDoc) *State {
+	if len(genDoc.Validators) == 0 {
+		util.Fatalf("The genesis file has no validators")
+	}
+
+	if genDoc.GenesisTime.IsZero() {
+		// NOTE: [ben] change GenesisTime to requirement on v0.17
+		// GenesisTime needs to be deterministic across the chain
+		// and should be required in the genesis file;
+		// the requirement is not yet enforced when lacking set
+		// time to 11/18/2016 @ 4:09am (UTC)
+		genDoc.GenesisTime = time.Unix(1479442162, 0)
+	}
+
+	// Make accounts state tree
+	accounts := iavl.NewIAVLTree(defaultAccountsCacheCapacity, db)
+	for _, genAcc := range genDoc.Accounts {
+		perm := genAcc.Permissions
+		acc := &acm.ConcreteAccount{
+			Address:     genAcc.Address,
+			Balance:     genAcc.Amount,
+			Permissions: perm,
+		}
+		accounts.Set(acc.Address.Bytes(), acc.Encode())
+	}
+
+	// global permissions are saved as the 0 address
+	// so they are included in the accounts tree
+	globalPerms := ptypes.DefaultAccountPermissions
+	globalPerms = genDoc.GlobalPermissions
+	// XXX: make sure the set bits are all true
+	// Without it the HasPermission() functions will fail
+	globalPerms.Base.SetBit = ptypes.AllPermFlags
+
+	permsAcc := &acm.ConcreteAccount{
+		Address:     permission.GlobalPermissionsAddress,
+		Balance:     1337,
+		Permissions: globalPerms,
+	}
+	accounts.Set(permsAcc.Address.Bytes(), permsAcc.Encode())
+
+	// Make validatorInfos state tree && validators slice
+	/*
+		validatorInfos := merkle.NewIAVLTree(wire.BasicCodec, types.ValidatorInfoCodec, 0, db)
+		validators := make([]*types.Validator, len(genDoc.Validators))
+		for i, val := range genDoc.Validators {
+			pubKey := val.PublicKey
+			address := pubKey.Address()
 
-	evc events.Fireable // typically an events.EventCache
+			// Make ValidatorInfo
+			valInfo := &types.ValidatorInfo{
+				Address:         address,
+				PublicKey:          pubKey,
+				UnbondTo:        make([]*types.TxOutput, len(val.UnbondTo)),
+				FirstBondHeight: 0,
+				FirstBondAmount: val.Amount,
+			}
+			for i, unbondTo := range val.UnbondTo {
+				valInfo.UnbondTo[i] = &types.TxOutput{
+					Address: unbondTo.Address,
+					Amount:  unbondTo.Amount,
+				}
+			}
+			validatorInfos.Set(address, valInfo)
+
+			// Make validator
+			validators[i] = &types.Validator{
+				Address:     address,
+				PublicKey:      pubKey,
+				VotingPower: val.Amount,
+			}
+		}
+	*/
+
+	// Make namereg tree
+	nameReg := iavl.NewIAVLTree(0, db)
+	// TODO: add names, contracts to genesis.json
+
+	// IAVLTrees must be persisted before copy operations.
+	accounts.Save()
+	//validatorInfos.Save()
+	nameReg.Save()
+
+	return &State{
+		db: db,
+		//BondedValidators:     types.NewValidatorSet(validators),
+		//LastBondedValidators: types.NewValidatorSet(nil),
+		//UnbondingValidators:  types.NewValidatorSet(nil),
+		accounts: accounts,
+		//validatorInfos:       validatorInfos,
+		nameReg: nameReg,
+	}
 }
 
-func LoadState(db dbm.DB) *State {
-	s := &State{DB: db}
+func LoadState(db dbm.DB) (*State, error) {
+	s := &State{db: db}
 	buf := db.Get(stateKey)
 	if len(buf) == 0 {
-		return nil
+		return nil, nil
 	} else {
 		r, n, err := bytes.NewReader(buf), new(int), new(error)
-		s.ChainID = wire.ReadString(r, maxLoadStateElementSize, n, err)
-		s.LastBlockHeight = wire.ReadVarint(r, n, err)
-		s.LastBlockHash = wire.ReadByteSlice(r, maxLoadStateElementSize, n, err)
-		s.LastBlockParts = wire.ReadBinary(types.PartSetHeader{}, r, maxLoadStateElementSize, n, err).(types.PartSetHeader)
-		s.LastBlockTime = wire.ReadTime(r, n, err)
-		// s.BondedValidators = wire.ReadBinary(&types.ValidatorSet{}, r, maxLoadStateElementSize, n, err).(*types.ValidatorSet)
-		// s.LastBondedValidators = wire.ReadBinary(&types.ValidatorSet{}, r, maxLoadStateElementSize, n, err).(*types.ValidatorSet)
-		// s.UnbondingValidators = wire.ReadBinary(&types.ValidatorSet{}, r, maxLoadStateElementSize, n, err).(*types.ValidatorSet)
-		accountsHash := wire.ReadByteSlice(r, maxLoadStateElementSize, n, err)
-		s.accounts = merkle.NewIAVLTree(defaultAccountsCacheCapacity, db)
-		s.accounts.Load(accountsHash)
-		//validatorInfosHash := wire.ReadByteSlice(r, maxLoadStateElementSize, n, err)
-		//s.validatorInfos = merkle.NewIAVLTree(wire.BasicCodec, types.ValidatorInfoCodec, 0, db)
-		//s.validatorInfos.Load(validatorInfosHash)
-		nameRegHash := wire.ReadByteSlice(r, maxLoadStateElementSize, n, err)
-		s.nameReg = merkle.NewIAVLTree(0, db)
-		s.nameReg.Load(nameRegHash)
+		wire.ReadBinaryPtr(&s, r, 0, n, err)
 		if *err != nil {
 			// DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
-			util.Fatalf("Data has been corrupted or its spec has changed: %v\n", *err)
+			return nil, fmt.Errorf("data has been corrupted or its spec has changed: %v", *err)
 		}
-		// TODO: ensure that buf is completely read.
 	}
-	return s
+	return s, nil
 }
 
 func (s *State) Save() {
+	s.Lock()
+	defer s.Unlock()
 	s.accounts.Save()
 	//s.validatorInfos.Save()
 	s.nameReg.Save()
-	buf, n, err := new(bytes.Buffer), new(int), new(error)
-	wire.WriteString(s.ChainID, buf, n, err)
-	wire.WriteVarint(s.LastBlockHeight, buf, n, err)
-	wire.WriteByteSlice(s.LastBlockHash, buf, n, err)
-	wire.WriteBinary(s.LastBlockParts, buf, n, err)
-	wire.WriteTime(s.LastBlockTime, buf, n, err)
-	// wire.WriteBinary(s.BondedValidators, buf, n, err)
-	// wire.WriteBinary(s.LastBondedValidators, buf, n, err)
-	// wire.WriteBinary(s.UnbondingValidators, buf, n, err)
-	wire.WriteByteSlice(s.accounts.Hash(), buf, n, err)
-	//wire.WriteByteSlice(s.validatorInfos.Hash(), buf, n, err)
-	wire.WriteByteSlice(s.nameReg.Hash(), buf, n, err)
-	if *err != nil {
-		// TODO: [Silas] Do something better than this, really serialising ought to
-		// be error-free
-		util.Fatalf("Could not serialise state in order to save the state, "+
-			"cannot continue, error: %s", *err)
-	}
-	s.DB.Set(stateKey, buf.Bytes())
+	s.db.SetSync(stateKey, wire.BinaryBytes(s))
 }
 
 // CONTRACT:
 // Copy() is a cheap way to take a snapshot,
 // as if State were copied by value.
+// TODO [Silas]: Kill this with fire it is totally broken - there is no safe way to copy IAVLTree while sharing database
 func (s *State) Copy() *State {
 	return &State{
-		DB:              s.DB,
-		ChainID:         s.ChainID,
-		LastBlockHeight: s.LastBlockHeight,
-		LastBlockHash:   s.LastBlockHash,
-		LastBlockParts:  s.LastBlockParts,
-		LastBlockTime:   s.LastBlockTime,
+		db: s.db,
 		// BondedValidators:     s.BondedValidators.Copy(),     // TODO remove need for Copy() here.
 		// LastBondedValidators: s.LastBondedValidators.Copy(), // That is, make updates to the validator set
 		// UnbondingValidators: s.UnbondingValidators.Copy(), // copy the valSet lazily.
 		accounts: s.accounts.Copy(),
 		//validatorInfos:       s.validatorInfos.Copy(),
 		nameReg: s.nameReg.Copy(),
-		evc:     nil,
 	}
 }
 
+//func (s *State) Copy() *State {
+//	stateCopy := &State{
+//		db:              dbm.NewMemDB(),
+//		chainID:         s.chainID,
+//		lastBlockHeight: s.lastBlockHeight,
+//		lastBlockAppHash:   s.lastBlockAppHash,
+//		lastBlockTime:   s.lastBlockTime,
+//		// BondedValidators:     s.BondedValidators.Copy(),     // TODO remove need for Copy() here.
+//		// LastBondedValidators: s.LastBondedValidators.Copy(), // That is, make updates to the validator set
+//		// UnbondingValidators: s.UnbondingValidators.Copy(), // copy the valSet lazily.
+//		accounts: copyTree(s.accounts),
+//		//validatorInfos:       s.validatorInfos.Copy(),
+//		nameReg: copyTree(s.nameReg),
+//		evc:     nil,
+//	}
+//	stateCopy.Save()
+//	return stateCopy
+//}
+
 // Returns a hash that represents the state data, excluding Last*
 func (s *State) Hash() []byte {
+	s.RLock()
+	defer s.RUnlock()
 	return merkle.SimpleHashFromMap(map[string]interface{}{
 		//"BondedValidators":    s.BondedValidators,
 		//"UnbondingValidators": s.UnbondingValidators,
-		"Accounts": s.accounts,
+		"Accounts": s.accounts.Hash(),
 		//"ValidatorInfos":      s.validatorInfos,
 		"NameRegistry": s.nameReg,
 	})
 }
 
-/* //XXX Done by tendermint core
-// Mutates the block in place and updates it with new state hash.
-func (s *State) ComputeBlockStateHash(block *types.Block) error {
-	sCopy := s.Copy()
-	// sCopy has no event cache in it, so this won't fire events
-	err := execBlock(sCopy, block, types.PartSetHeader{})
-	if err != nil {
-		return err
-	}
-	// Set block.StateHash
-	block.StateHash = sCopy.Hash()
-	return nil
-}
-*/
-
-func (s *State) GetGenesisDoc() (*genesis.GenesisDoc, error) {
-	var genesisDoc *genesis.GenesisDoc
-	loadedGenesisDocBytes := s.DB.Get(genesis.GenDocKey)
-	err := new(error)
-	wire.ReadJSONPtr(&genesisDoc, loadedGenesisDocBytes, err)
-	if *err != nil {
-		return nil, fmt.Errorf("Unable to read genesisDoc from db on Get: %v", err)
-	}
-	return genesisDoc, nil
-}
-
-func (s *State) SetDB(db dbm.DB) {
-	s.DB = db
-}
-
-//-------------------------------------
-// State.params
-
-func (s *State) GetGasLimit() int64 {
-	return 1000000 // TODO
-}
-
-// State.params
-//-------------------------------------
-// State.accounts
-
 // Returns nil if account does not exist with given address.
-// Implements Statelike
-func (s *State) GetAccount(address []byte) *acm.Account {
-	_, accBytes, _ := s.accounts.Get(address)
+func (s *State) GetAccount(address acm.Address) (acm.Account, error) {
+	s.RLock()
+	defer s.RUnlock()
+	_, accBytes, _ := s.accounts.Get(address.Bytes())
 	if accBytes == nil {
-		return nil
+		return nil, nil
 	}
-	return acm.DecodeAccount(accBytes)
+	return acm.Decode(accBytes)
 }
 
-// The account is copied before setting, so mutating it
-// afterwards has no side effects.
-// Implements Statelike
-func (s *State) UpdateAccount(account *acm.Account) bool {
-	return s.accounts.Set(account.Address, acm.EncodeAccount(account))
+func (s *State) UpdateAccount(account acm.Account) error {
+	s.Lock()
+	defer s.Unlock()
+	s.accounts.Set(account.Address().Bytes(), account.Encode())
+	return nil
 }
 
-// Implements Statelike
-func (s *State) RemoveAccount(address []byte) bool {
-	_, removed := s.accounts.Remove(address)
-	return removed
+func (s *State) RemoveAccount(address acm.Address) error {
+	s.Lock()
+	defer s.Unlock()
+	s.accounts.Remove(address.Bytes())
+	return nil
 }
 
-// The returned Account is a copy, so mutating it
-// has no side effects.
+// This does not give a true independent copy since the underlying database is shared and any save calls all copies
+// to become invalid and using them may cause panics
 func (s *State) GetAccounts() merkle.Tree {
 	return s.accounts.Copy()
 }
 
-// Set the accounts tree
-func (s *State) SetAccounts(accounts merkle.Tree) {
-	s.accounts = accounts
+func (s *State) IterateAccounts(consumer func(acm.Account) (stop bool)) (stopped bool, err error) {
+	s.RLock()
+	defer s.RUnlock()
+	stopped = s.accounts.Iterate(func(key, value []byte) bool {
+		var account acm.Account
+		account, err = acm.Decode(value)
+		if err != nil {
+			return true
+		}
+		return consumer(account)
+	})
+	return
 }
 
 // State.accounts
@@ -265,7 +314,7 @@ func (s *State) unbondValidator(val *types.Validator) {
 	if !removed {
 		PanicCrisis("Couldn't remove validator for unbonding")
 	}
-	val.UnbondHeight = s.LastBlockHeight + 1
+	val.UnbondHeight = s.lastBlockHeight + 1
 	added := s.UnbondingValidators.Add(val)
 	if !added {
 		PanicCrisis("Couldn't add validator for unbonding")
@@ -278,7 +327,7 @@ func (s *State) rebondValidator(val *types.Validator) {
 	if !removed {
 		PanicCrisis("Couldn't remove validator for rebonding")
 	}
-	val.BondHeight = s.LastBlockHeight + 1
+	val.BondHeight = s.lastBlockHeight + 1
 	added := s.BondedValidators.Add(val)
 	if !added {
 		PanicCrisis("Couldn't add validator for rebonding")
@@ -291,7 +340,7 @@ func (s *State) releaseValidator(val *types.Validator) {
 	if valInfo == nil {
 		PanicSanity("Couldn't find validatorInfo for release")
 	}
-	valInfo.ReleasedHeight = s.LastBlockHeight + 1
+	valInfo.ReleasedHeight = s.lastBlockHeight + 1
 	s.SetValidatorInfo(valInfo)
 
 	// Send coins back to UnbondTo outputs
@@ -317,7 +366,7 @@ func (s *State) destroyValidator(val *types.Validator) {
 	if valInfo == nil {
 		PanicSanity("Couldn't find validatorInfo for release")
 	}
-	valInfo.DestroyedHeight = s.LastBlockHeight + 1
+	valInfo.DestroyedHeight = s.lastBlockHeight + 1
 	valInfo.DestroyedAmount = val.VotingPower
 	s.SetValidatorInfo(valInfo)
 
@@ -343,17 +392,81 @@ func (s *State) SetValidatorInfos(validatorInfos merkle.Tree) {
 //-------------------------------------
 // State.storage
 
-func (s *State) LoadStorage(hash []byte) (storage merkle.Tree) {
-	storage = merkle.NewIAVLTree(1024, s.DB)
+func (s *State) accountStorage(address acm.Address) (merkle.Tree, error) {
+	account, err := s.GetAccount(address)
+	if err != nil {
+		return nil, err
+	}
+	if account == nil {
+		return nil, fmt.Errorf("could not find account %s to access its storage", address)
+	}
+	return s.LoadStorage(account.StorageRoot()), nil
+}
+
+func (s *State) LoadStorage(hash []byte) merkle.Tree {
+	s.RLock()
+	defer s.RUnlock()
+	storage := iavl.NewIAVLTree(1024, s.db)
 	storage.Load(hash)
 	return storage
 }
 
+func (s *State) GetStorage(address acm.Address, key binary.Word256) (binary.Word256, error) {
+	s.RLock()
+	defer s.RUnlock()
+	storageTree, err := s.accountStorage(address)
+	if err != nil {
+		return binary.Zero256, err
+	}
+	_, value, _ := storageTree.Get(key.Bytes())
+	return binary.LeftPadWord256(value), nil
+}
+
+func (s *State) SetStorage(address acm.Address, key, value binary.Word256) error {
+	s.Lock()
+	defer s.Unlock()
+	storageTree, err := s.accountStorage(address)
+	if err != nil {
+		return err
+	}
+	if storageTree != nil {
+		storageTree.Set(key.Bytes(), value.Bytes())
+	}
+	return nil
+}
+
+func (s *State) IterateStorage(address acm.Address,
+	consumer func(key, value binary.Word256) (stop bool)) (stopped bool, err error) {
+
+	var storageTree merkle.Tree
+	storageTree, err = s.accountStorage(address)
+	if err != nil {
+		return
+	}
+	stopped = storageTree.Iterate(func(key []byte, value []byte) (stop bool) {
+		// Note: no left padding should occur unless there is a bug and non-words have been writte to this storage tree
+		if len(key) != binary.Word256Length {
+			err = fmt.Errorf("key '%X' stored for account %s is not a %v-byte word",
+				key, address, binary.Word256Length)
+			return true
+		}
+		if len(value) != binary.Word256Length {
+			err = fmt.Errorf("value '%X' stored for account %s is not a %v-byte word",
+				key, address, binary.Word256Length)
+			return true
+		}
+		return consumer(binary.LeftPadWord256(key), binary.LeftPadWord256(value))
+	})
+	return
+}
+
 // State.storage
 //-------------------------------------
 // State.nameReg
 
-func (s *State) GetNameRegEntry(name string) *core_types.NameRegEntry {
+var _ NameRegIterable = &State{}
+
+func (s *State) GetNameRegEntry(name string) *NameRegEntry {
 	_, valueBytes, _ := s.nameReg.Get([]byte(name))
 	if valueBytes == nil {
 		return nil
@@ -362,18 +475,24 @@ func (s *State) GetNameRegEntry(name string) *core_types.NameRegEntry {
 	return DecodeNameRegEntry(valueBytes)
 }
 
-func DecodeNameRegEntry(entryBytes []byte) *core_types.NameRegEntry {
+func (s *State) IterateNameRegEntries(consumer func(*NameRegEntry) (stop bool)) (stopped bool) {
+	return s.nameReg.Iterate(func(key []byte, value []byte) (stop bool) {
+		return consumer(DecodeNameRegEntry(value))
+	})
+}
+
+func DecodeNameRegEntry(entryBytes []byte) *NameRegEntry {
 	var n int
 	var err error
-	value := NameRegCodec.Decode(bytes.NewBuffer(entryBytes), &n, &err)
-	return value.(*core_types.NameRegEntry)
+	value := NameRegDecode(bytes.NewBuffer(entryBytes), &n, &err)
+	return value.(*NameRegEntry)
 }
 
-func (s *State) UpdateNameRegEntry(entry *core_types.NameRegEntry) bool {
+func (s *State) UpdateNameRegEntry(entry *NameRegEntry) bool {
 	w := new(bytes.Buffer)
 	var n int
 	var err error
-	NameRegCodec.Encode(entry, w, &n, &err)
+	NameRegEncode(entry, w, &n, &err)
 	return s.nameReg.Set([]byte(entry.Name), w.Bytes())
 }
 
@@ -390,144 +509,10 @@ func (s *State) GetNames() merkle.Tree {
 func (s *State) SetNameReg(nameReg merkle.Tree) {
 	s.nameReg = nameReg
 }
-
-func NameRegEncoder(o interface{}, w io.Writer, n *int, err *error) {
-	wire.WriteBinary(o.(*core_types.NameRegEntry), w, n, err)
-}
-
-func NameRegDecoder(r io.Reader, n *int, err *error) interface{} {
-	return wire.ReadBinary(&core_types.NameRegEntry{}, r, txs.MaxDataLength, n, err)
+func NameRegEncode(o interface{}, w io.Writer, n *int, err *error) {
+	wire.WriteBinary(o.(*NameRegEntry), w, n, err)
 }
 
-var NameRegCodec = wire.Codec{
-	Encode: NameRegEncoder,
-	Decode: NameRegDecoder,
-}
-
-// State.nameReg
-//-------------------------------------
-
-// Implements events.Eventable. Typically uses events.EventCache
-func (s *State) SetFireable(evc events.Fireable) {
-	s.evc = evc
-}
-
-//-----------------------------------------------------------------------------
-// Genesis
-
-func MakeGenesisStateFromFile(db dbm.DB, genDocFile string) (*genesis.GenesisDoc, *State) {
-	jsonBlob, err := ioutil.ReadFile(genDocFile)
-	if err != nil {
-		util.Fatalf("Couldn't read GenesisDoc file: %v", err)
-	}
-	genDoc := genesis.GenesisDocFromJSON(jsonBlob)
-	return genDoc, MakeGenesisState(db, genDoc)
-}
-
-func MakeGenesisState(db dbm.DB, genDoc *genesis.GenesisDoc) *State {
-	if len(genDoc.Validators) == 0 {
-		util.Fatalf("The genesis file has no validators")
-	}
-
-	if genDoc.GenesisTime.IsZero() {
-		// NOTE: [ben] change GenesisTime to requirement on v0.17
-		// GenesisTime needs to be deterministic across the chain
-		// and should be required in the genesis file;
-		// the requirement is not yet enforced when lacking set
-		// time to 11/18/2016 @ 4:09am (UTC)
-		genDoc.GenesisTime = time.Unix(1479442162, 0)
-	}
-
-	// Make accounts state tree
-	accounts := merkle.NewIAVLTree(defaultAccountsCacheCapacity, db)
-	for _, genAcc := range genDoc.Accounts {
-		perm := ptypes.ZeroAccountPermissions
-		if genAcc.Permissions != nil {
-			perm = *genAcc.Permissions
-		}
-		acc := &acm.Account{
-			Address:     genAcc.Address,
-			PubKey:      nil,
-			Sequence:    0,
-			Balance:     genAcc.Amount,
-			Permissions: perm,
-		}
-		accounts.Set(acc.Address, acm.EncodeAccount(acc))
-	}
-
-	// global permissions are saved as the 0 address
-	// so they are included in the accounts tree
-	globalPerms := ptypes.DefaultAccountPermissions
-	if genDoc.Params != nil && genDoc.Params.GlobalPermissions != nil {
-		globalPerms = *genDoc.Params.GlobalPermissions
-		// XXX: make sure the set bits are all true
-		// Without it the HasPermission() functions will fail
-		globalPerms.Base.SetBit = ptypes.AllPermFlags
-	}
-
-	permsAcc := &acm.Account{
-		Address:     ptypes.GlobalPermissionsAddress,
-		PubKey:      nil,
-		Sequence:    0,
-		Balance:     1337,
-		Permissions: globalPerms,
-	}
-	accounts.Set(permsAcc.Address, acm.EncodeAccount(permsAcc))
-
-	// Make validatorInfos state tree && validators slice
-	/*
-		validatorInfos := merkle.NewIAVLTree(wire.BasicCodec, types.ValidatorInfoCodec, 0, db)
-		validators := make([]*types.Validator, len(genDoc.Validators))
-		for i, val := range genDoc.Validators {
-			pubKey := val.PubKey
-			address := pubKey.Address()
-
-			// Make ValidatorInfo
-			valInfo := &types.ValidatorInfo{
-				Address:         address,
-				PubKey:          pubKey,
-				UnbondTo:        make([]*types.TxOutput, len(val.UnbondTo)),
-				FirstBondHeight: 0,
-				FirstBondAmount: val.Amount,
-			}
-			for i, unbondTo := range val.UnbondTo {
-				valInfo.UnbondTo[i] = &types.TxOutput{
-					Address: unbondTo.Address,
-					Amount:  unbondTo.Amount,
-				}
-			}
-			validatorInfos.Set(address, valInfo)
-
-			// Make validator
-			validators[i] = &types.Validator{
-				Address:     address,
-				PubKey:      pubKey,
-				VotingPower: val.Amount,
-			}
-		}
-	*/
-
-	// Make namereg tree
-	nameReg := merkle.NewIAVLTree(0, db)
-	// TODO: add names, contracts to genesis.json
-
-	// IAVLTrees must be persisted before copy operations.
-	accounts.Save()
-	//validatorInfos.Save()
-	nameReg.Save()
-
-	return &State{
-		DB:              db,
-		ChainID:         genDoc.ChainID,
-		LastBlockHeight: 0,
-		LastBlockHash:   nil,
-		LastBlockParts:  types.PartSetHeader{},
-		LastBlockTime:   genDoc.GenesisTime,
-		//BondedValidators:     types.NewValidatorSet(validators),
-		//LastBondedValidators: types.NewValidatorSet(nil),
-		//UnbondingValidators:  types.NewValidatorSet(nil),
-		accounts: accounts,
-		//validatorInfos:       validatorInfos,
-		nameReg: nameReg,
-	}
+func NameRegDecode(r io.Reader, n *int, err *error) interface{} {
+	return wire.ReadBinary(&NameRegEntry{}, r, txs.MaxDataLength, n, err)
 }
diff --git a/manager/burrow-mint/state/state_test.go b/execution/state_test.go
similarity index 51%
rename from manager/burrow-mint/state/state_test.go
rename to execution/state_test.go
index f9f91d9b..909b77d0 100644
--- a/manager/burrow-mint/state/state_test.go
+++ b/execution/state_test.go
@@ -12,48 +12,88 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package state
+package execution
 
 import (
 	"bytes"
 	"encoding/hex"
 	"testing"
 
-	core_types "github.com/hyperledger/burrow/core/types"
-	evm "github.com/hyperledger/burrow/manager/burrow-mint/evm"
-	"github.com/hyperledger/burrow/txs"
-	"github.com/hyperledger/burrow/word256"
+	"fmt"
+
+	"github.com/hyperledger/burrow/execution/evm/sha3"
 
-	"github.com/tendermint/tendermint/config/tendermint_test"
+	"time"
+
+	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/binary"
+	bcm "github.com/hyperledger/burrow/blockchain"
+	"github.com/hyperledger/burrow/event"
+	"github.com/hyperledger/burrow/genesis"
+	"github.com/hyperledger/burrow/txs"
+	"github.com/stretchr/testify/assert"
+	dbm "github.com/tendermint/tmlibs/db"
 )
 
-func init() {
-	tendermint_test.ResetConfig("state_test")
-	evm.SetDebug(true)
-}
+var deterministicGenesis = genesis.NewDeterministicGenesis(34059836243380576)
+var testGenesisDoc, testPrivAccounts = deterministicGenesis.
+	GenesisDoc(3, true, 1000, 1, true, 1000)
+var testChainID = testGenesisDoc.ChainID()
 
-func execTxWithState(state *State, tx txs.Tx, runCall bool) error {
-	cache := NewBlockCache(state)
-	if err := ExecTx(cache, tx, runCall, nil, logger); err != nil {
+func execTxWithStateAndBlockchain(state *State, tip bcm.Tip, tx txs.Tx) error {
+	exe := newExecutor(true, state, testChainID, tip, event.NewNoOpFireable(), logger)
+	if err := exe.Execute(tx); err != nil {
 		return err
 	} else {
-		cache.Sync()
+		exe.blockCache.Sync()
 		return nil
 	}
 }
 
-func execTxWithStateNewBlock(state *State, tx txs.Tx, runCall bool) error {
-	if err := execTxWithState(state, tx, runCall); err != nil {
+func execTxWithState(state *State, tx txs.Tx) error {
+	return execTxWithStateAndBlockchain(state, bcm.NewBlockchain(testGenesisDoc), tx)
+}
+
+func commitNewBlock(state *State, blockchain bcm.MutableBlockchain) {
+	blockchain.CommitBlock(blockchain.LastBlockTime().Add(time.Second), sha3.Sha3(blockchain.LastBlockHash()),
+		state.Hash())
+}
+
+func execTxWithStateNewBlock(state *State, blockchain bcm.MutableBlockchain, tx txs.Tx) error {
+	if err := execTxWithStateAndBlockchain(state, blockchain, tx); err != nil {
 		return err
 	}
-
-	state.LastBlockHeight += 1
+	commitNewBlock(state, blockchain)
 	return nil
 }
 
+func makeGenesisState(numAccounts int, randBalance bool, minBalance uint64, numValidators int, randBonded bool,
+	minBonded int64) (*State, []acm.PrivateAccount) {
+	testGenesisDoc, privAccounts := deterministicGenesis.GenesisDoc(numAccounts, randBalance, minBalance,
+		numValidators, randBonded, minBonded)
+	s0 := MakeGenesisState(dbm.NewMemDB(), testGenesisDoc)
+	s0.Save()
+	return s0, privAccounts
+}
+
+func getAccount(state acm.Getter, address acm.Address) acm.MutableAccount {
+	acc, _ := acm.GetMutableAccount(state, address)
+	return acc
+}
+
+func addressPtr(account acm.Account) *acm.Address {
+	if account == nil {
+		return nil
+	}
+	accountAddresss := account.Address()
+	return &accountAddresss
+}
+
+// Tests
+
 func TestCopyState(t *testing.T) {
 	// Generate a random state
-	s0, privAccounts, _ := RandGenesisState(10, true, 1000, 5, true, 1000)
+	s0, privAccounts := makeGenesisState(10, true, 1000, 5, true, 1000)
 	s0Hash := s0.Hash()
 	if len(s0Hash) == 0 {
 		t.Error("Expected state hash")
@@ -61,23 +101,22 @@ func TestCopyState(t *testing.T) {
 
 	// Check hash of copy
 	s0Copy := s0.Copy()
-	if !bytes.Equal(s0Hash, s0Copy.Hash()) {
-		t.Error("Expected state copy hash to be the same")
-	}
+	assert.Equal(t, s0Hash, s0Copy.Hash(), "Expected state copy hash to be the same")
+	assert.Equal(t, s0Copy.Copy().Hash(), s0Copy.Hash(), "Expected COPY COPY COPY the same")
 
 	// Mutate the original; hash should change.
-	acc0Address := privAccounts[0].PubKey.Address()
-	acc := s0.GetAccount(acc0Address)
-	acc.Balance += 1
+	acc0Address := privAccounts[0].Address()
+	acc := getAccount(s0, acc0Address)
+	acc.AddToBalance(1)
 
 	// The account balance shouldn't have changed yet.
-	if s0.GetAccount(acc0Address).Balance == acc.Balance {
+	if getAccount(s0, acc0Address).Balance() == acc.Balance() {
 		t.Error("Account balance changed unexpectedly")
 	}
 
 	// Setting, however, should change the balance.
 	s0.UpdateAccount(acc)
-	if s0.GetAccount(acc0Address).Balance != acc.Balance {
+	if getAccount(s0, acc0Address).Balance() != acc.Balance() {
 		t.Error("Account balance wasn't set")
 	}
 
@@ -99,11 +138,11 @@ func makeBlock(t *testing.T, state *State, validation *tmtypes.Commit, txs []txs
 	}
 	block := &tmtypes.Block{
 		Header: &tmtypes.Header{
-			ChainID:        state.ChainID,
-			Height:         state.LastBlockHeight + 1,
-			Time:           state.LastBlockTime.Add(time.Minute),
+			testChainID:        testChainID,
+			Height:         blockchain.LastBlockHeight() + 1,
+			Time:           state.lastBlockTime.Add(time.Minute),
 			NumTxs:         len(txs),
-			LastBlockHash:  state.LastBlockHash,
+			lastBlockAppHash:  state.lastBlockAppHash,
 			LastBlockParts: state.LastBlockParts,
 			AppHash:        nil,
 		},
@@ -129,7 +168,7 @@ func makeBlock(t *testing.T, state *State, validation *tmtypes.Commit, txs []txs
 func TestGenesisSaveLoad(t *testing.T) {
 
 	// Generate a state, save & load it.
-	s0, _, _ := RandGenesisState(10, true, 1000, 5, true, 1000)
+	s0, _, _ := makeGenesisState(10, true, 1000, 5, true, 1000)
 
 	// Make complete block and blockParts
 	block := makeBlock(t, s0, nil, nil)
@@ -145,23 +184,23 @@ func TestGenesisSaveLoad(t *testing.T) {
 	s0.Save()
 
 	// Sanity check s0
-	//s0.DB.(*dbm.MemDB).Print()
+	//s0.db.(*dbm.MemDB).Print()
 	if s0.BondedValidators.TotalVotingPower() == 0 {
 		t.Error("s0 BondedValidators TotalVotingPower should not be 0")
 	}
-	if s0.LastBlockHeight != 1 {
-		t.Error("s0 LastBlockHeight should be 1, got", s0.LastBlockHeight)
+	if s0.lastBlockHeight != 1 {
+		t.Error("s0 lastBlockHeight should be 1, got", s0.lastBlockHeight)
 	}
 
 	// Load s1
-	s1 := LoadState(s0.DB)
+	s1 := LoadState(s0.db)
 
 	// Compare height & blockHash
-	if s0.LastBlockHeight != s1.LastBlockHeight {
-		t.Error("LastBlockHeight mismatch")
+	if s0.lastBlockHeight != s1.lastBlockHeight {
+		t.Error("lastBlockHeight mismatch")
 	}
-	if !bytes.Equal(s0.LastBlockHash, s1.LastBlockHash) {
-		t.Error("LastBlockHash mismatch")
+	if !bytes.Equal(s0.lastBlockAppHash, s1.lastBlockAppHash) {
+		t.Error("lastBlockAppHash mismatch")
 	}
 
 	// Compare state merkle trees
@@ -194,64 +233,68 @@ func TestGenesisSaveLoad(t *testing.T) {
 
 func TestTxSequence(t *testing.T) {
 
-	state, privAccounts, _ := RandGenesisState(3, true, 1000, 1, true, 1000)
-	acc0 := state.GetAccount(privAccounts[0].PubKey.Address())
-	acc0PubKey := privAccounts[0].PubKey
-	acc1 := state.GetAccount(privAccounts[1].PubKey.Address())
+	state, privAccounts := makeGenesisState(3, true, 1000, 1, true, 1000)
+	acc0 := getAccount(state, privAccounts[0].Address())
+	acc0PubKey := privAccounts[0].PublicKey()
+	acc1 := getAccount(state, privAccounts[1].Address())
 
 	// Test a variety of sequence numbers for the tx.
 	// The tx should only pass when i == 1.
-	for i := -1; i < 3; i++ {
-		sequence := acc0.Sequence + i
+	for i := uint64(0); i < 3; i++ {
+		sequence := acc0.Sequence() + i
 		tx := txs.NewSendTx()
 		tx.AddInputWithNonce(acc0PubKey, 1, sequence)
-		tx.AddOutput(acc1.Address, 1)
-		tx.Inputs[0].Signature = privAccounts[0].Sign(state.ChainID, tx)
+		tx.AddOutput(acc1.Address(), 1)
+		tx.Inputs[0].Signature = acm.ChainSign(privAccounts[0], testChainID, tx)
 		stateCopy := state.Copy()
-		err := execTxWithState(stateCopy, tx, true)
+		err := execTxWithState(stateCopy, tx)
 		if i == 1 {
 			// Sequence is good.
 			if err != nil {
 				t.Errorf("Expected good sequence to pass: %v", err)
 			}
-			// Check acc.Sequence.
-			newAcc0 := stateCopy.GetAccount(acc0.Address)
-			if newAcc0.Sequence != sequence {
+			// Check acc.Sequence().
+			newAcc0 := getAccount(stateCopy, acc0.Address())
+			if newAcc0.Sequence() != sequence {
 				t.Errorf("Expected account sequence to change to %v, got %v",
-					sequence, newAcc0.Sequence)
+					sequence, newAcc0.Sequence())
 			}
 		} else {
 			// Sequence is bad.
 			if err == nil {
 				t.Errorf("Expected bad sequence to fail")
 			}
-			// Check acc.Sequence. (shouldn't have changed)
-			newAcc0 := stateCopy.GetAccount(acc0.Address)
-			if newAcc0.Sequence != acc0.Sequence {
+			// Check acc.Sequence(). (shouldn't have changed)
+			newAcc0 := getAccount(stateCopy, acc0.Address())
+			if newAcc0.Sequence() != acc0.Sequence() {
 				t.Errorf("Expected account sequence to not change from %v, got %v",
-					acc0.Sequence, newAcc0.Sequence)
+					acc0.Sequence(), newAcc0.Sequence())
 			}
 		}
 	}
 }
 
 func TestNameTxs(t *testing.T) {
-	state, privAccounts, _ := RandGenesisState(3, true, 1000, 1, true, 1000)
+	state := MakeGenesisState(dbm.NewMemDB(), testGenesisDoc)
+	state.Save()
 
 	txs.MinNameRegistrationPeriod = 5
-	startingBlock := state.LastBlockHeight
+	blockchain := bcm.NewBlockchain(testGenesisDoc)
+	startingBlock := blockchain.LastBlockHeight()
 
 	// try some bad names. these should all fail
-	names := []string{"", "\n", "123#$%", "\x00", string([]byte{20, 40, 60, 80}), "baffledbythespectacleinallofthisyouseeehesaidwithouteyessurprised", "no spaces please"}
+	names := []string{"", "\n", "123#$%", "\x00", string([]byte{20, 40, 60, 80}),
+		"baffledbythespectacleinallofthisyouseeehesaidwithouteyessurprised", "no spaces please"}
 	data := "something about all this just doesn't feel right."
-	fee := int64(1000)
-	numDesiredBlocks := 5
+	fee := uint64(1000)
+	numDesiredBlocks := uint64(5)
 	for _, name := range names {
-		amt := fee + int64(numDesiredBlocks)*txs.NameByteCostMultiplier*txs.NameBlockCostMultiplier*txs.NameBaseCost(name, data)
-		tx, _ := txs.NewNameTx(state, privAccounts[0].PubKey, name, data, amt, fee)
-		tx.Sign(state.ChainID, privAccounts[0])
+		amt := fee + numDesiredBlocks*txs.NameByteCostMultiplier*txs.NameBlockCostMultiplier*
+			txs.NameBaseCost(name, data)
+		tx, _ := txs.NewNameTx(state, testPrivAccounts[0].PublicKey(), name, data, amt, fee)
+		tx.Sign(testChainID, testPrivAccounts[0])
 
-		if err := execTxWithState(state, tx, true); err == nil {
+		if err := execTxWithState(state, tx); err == nil {
 			t.Fatalf("Expected invalid name error from %s", name)
 		}
 	}
@@ -260,23 +303,23 @@ func TestNameTxs(t *testing.T) {
 	name := "hold_it_chum"
 	datas := []string{"cold&warm", "!@#$%^&*()", "<<<>>>>", "because why would you ever need a ~ or a & or even a % in a json file? make your case and we'll talk"}
 	for _, data := range datas {
-		amt := fee + int64(numDesiredBlocks)*txs.NameByteCostMultiplier*txs.NameBlockCostMultiplier*txs.NameBaseCost(name, data)
-		tx, _ := txs.NewNameTx(state, privAccounts[0].PubKey, name, data, amt, fee)
-		tx.Sign(state.ChainID, privAccounts[0])
+		amt := fee + numDesiredBlocks*txs.NameByteCostMultiplier*txs.NameBlockCostMultiplier*
+			txs.NameBaseCost(name, data)
+		tx, _ := txs.NewNameTx(state, testPrivAccounts[0].PublicKey(), name, data, amt, fee)
+		tx.Sign(testChainID, testPrivAccounts[0])
 
-		if err := execTxWithState(state, tx, true); err == nil {
+		if err := execTxWithState(state, tx); err == nil {
 			t.Fatalf("Expected invalid data error from %s", data)
 		}
 	}
 
-	validateEntry := func(t *testing.T, entry *core_types.NameRegEntry, name,
-		data string, addr []byte, expires int) {
+	validateEntry := func(t *testing.T, entry *NameRegEntry, name, data string, addr acm.Address, expires uint64) {
 
 		if entry == nil {
 			t.Fatalf("Could not find name %s", name)
 		}
-		if !bytes.Equal(entry.Owner, addr) {
-			t.Fatalf("Wrong owner. Got %X expected %X", entry.Owner, addr)
+		if entry.Owner != addr {
+			t.Fatalf("Wrong owner. Got %s expected %s", entry.Owner, addr)
 		}
 		if data != entry.Data {
 			t.Fatalf("Wrong data. Got %s expected %s", entry.Data, data)
@@ -292,78 +335,81 @@ func TestNameTxs(t *testing.T) {
 	// try a good one, check data, owner, expiry
 	name = "@looking_good/karaoke_bar.broadband"
 	data = "on this side of neptune there are 1234567890 people: first is OMNIVORE+-3. Or is it. Ok this is pretty restrictive. No exclamations :(. Faces tho :')"
-	amt := fee + int64(numDesiredBlocks)*txs.NameByteCostMultiplier*txs.NameBlockCostMultiplier*txs.NameBaseCost(name, data)
-	tx, _ := txs.NewNameTx(state, privAccounts[0].PubKey, name, data, amt, fee)
-	tx.Sign(state.ChainID, privAccounts[0])
-	if err := execTxWithState(state, tx, true); err != nil {
+	amt := fee + numDesiredBlocks*txs.NameByteCostMultiplier*txs.NameBlockCostMultiplier*txs.NameBaseCost(name, data)
+	tx, _ := txs.NewNameTx(state, testPrivAccounts[0].PublicKey(), name, data, amt, fee)
+	tx.Sign(testChainID, testPrivAccounts[0])
+	if err := execTxWithState(state, tx); err != nil {
 		t.Fatal(err)
 	}
 	entry := state.GetNameRegEntry(name)
-	validateEntry(t, entry, name, data, privAccounts[0].Address, startingBlock+numDesiredBlocks)
+	validateEntry(t, entry, name, data, testPrivAccounts[0].Address(), startingBlock+numDesiredBlocks)
 
 	// fail to update it as non-owner, in same block
-	tx, _ = txs.NewNameTx(state, privAccounts[1].PubKey, name, data, amt, fee)
-	tx.Sign(state.ChainID, privAccounts[1])
-	if err := execTxWithState(state, tx, true); err == nil {
+	tx, _ = txs.NewNameTx(state, testPrivAccounts[1].PublicKey(), name, data, amt, fee)
+	tx.Sign(testChainID, testPrivAccounts[1])
+	if err := execTxWithState(state, tx); err == nil {
 		t.Fatal("Expected error")
 	}
 
 	// update it as owner, just to increase expiry, in same block
 	// NOTE: we have to resend the data or it will clear it (is this what we want?)
-	tx, _ = txs.NewNameTx(state, privAccounts[0].PubKey, name, data, amt, fee)
-	tx.Sign(state.ChainID, privAccounts[0])
-	if err := execTxWithStateNewBlock(state, tx, true); err != nil {
+	tx, _ = txs.NewNameTx(state, testPrivAccounts[0].PublicKey(), name, data, amt, fee)
+	tx.Sign(testChainID, testPrivAccounts[0])
+	if err := execTxWithStateNewBlock(state, blockchain, tx); err != nil {
 		t.Fatal(err)
 	}
 	entry = state.GetNameRegEntry(name)
-	validateEntry(t, entry, name, data, privAccounts[0].Address, startingBlock+numDesiredBlocks*2)
+	validateEntry(t, entry, name, data, testPrivAccounts[0].Address(), startingBlock+numDesiredBlocks*2)
 
 	// update it as owner, just to increase expiry, in next block
-	tx, _ = txs.NewNameTx(state, privAccounts[0].PubKey, name, data, amt, fee)
-	tx.Sign(state.ChainID, privAccounts[0])
-	if err := execTxWithStateNewBlock(state, tx, true); err != nil {
+	tx, _ = txs.NewNameTx(state, testPrivAccounts[0].PublicKey(), name, data, amt, fee)
+	tx.Sign(testChainID, testPrivAccounts[0])
+	if err := execTxWithStateNewBlock(state, blockchain, tx); err != nil {
 		t.Fatal(err)
 	}
 	entry = state.GetNameRegEntry(name)
-	validateEntry(t, entry, name, data, privAccounts[0].Address, startingBlock+numDesiredBlocks*3)
+	validateEntry(t, entry, name, data, testPrivAccounts[0].Address(), startingBlock+numDesiredBlocks*3)
 
 	// fail to update it as non-owner
-	state.LastBlockHeight = entry.Expires - 1
-	tx, _ = txs.NewNameTx(state, privAccounts[1].PubKey, name, data, amt, fee)
-	tx.Sign(state.ChainID, privAccounts[1])
-	if err := execTxWithState(state, tx, true); err == nil {
+	// Fast forward
+	for blockchain.Tip().LastBlockHeight() < entry.Expires-1 {
+		commitNewBlock(state, blockchain)
+	}
+	tx, _ = txs.NewNameTx(state, testPrivAccounts[1].PublicKey(), name, data, amt, fee)
+	tx.Sign(testChainID, testPrivAccounts[1])
+	if err := execTxWithStateAndBlockchain(state, blockchain, tx); err == nil {
 		t.Fatal("Expected error")
 	}
+	commitNewBlock(state, blockchain)
 
 	// once expires, non-owner succeeds
-	state.LastBlockHeight = entry.Expires
-	tx, _ = txs.NewNameTx(state, privAccounts[1].PubKey, name, data, amt, fee)
-	tx.Sign(state.ChainID, privAccounts[1])
-	if err := execTxWithState(state, tx, true); err != nil {
+	tx, _ = txs.NewNameTx(state, testPrivAccounts[1].PublicKey(), name, data, amt, fee)
+	tx.Sign(testChainID, testPrivAccounts[1])
+	if err := execTxWithStateAndBlockchain(state, blockchain, tx); err != nil {
 		t.Fatal(err)
 	}
 	entry = state.GetNameRegEntry(name)
-	validateEntry(t, entry, name, data, privAccounts[1].Address, state.LastBlockHeight+numDesiredBlocks)
+	validateEntry(t, entry, name, data, testPrivAccounts[1].Address(), blockchain.LastBlockHeight()+numDesiredBlocks)
 
 	// update it as new owner, with new data (longer), but keep the expiry!
 	data = "In the beginning there was no thing, not even the beginning. It hadn't been here, no there, nor for that matter anywhere, not especially because it had not to even exist, let alone to not. Nothing especially odd about that."
 	oldCredit := amt - fee
 	numDesiredBlocks = 10
-	amt = fee + (int64(numDesiredBlocks)*txs.NameByteCostMultiplier*txs.NameBlockCostMultiplier*txs.NameBaseCost(name, data) - oldCredit)
-	tx, _ = txs.NewNameTx(state, privAccounts[1].PubKey, name, data, amt, fee)
-	tx.Sign(state.ChainID, privAccounts[1])
-	if err := execTxWithState(state, tx, true); err != nil {
+	amt = fee + numDesiredBlocks*txs.NameByteCostMultiplier*txs.NameBlockCostMultiplier*txs.NameBaseCost(name, data) - oldCredit
+	tx, _ = txs.NewNameTx(state, testPrivAccounts[1].PublicKey(), name, data, amt, fee)
+	tx.Sign(testChainID, testPrivAccounts[1])
+	if err := execTxWithStateAndBlockchain(state, blockchain, tx); err != nil {
 		t.Fatal(err)
 	}
 	entry = state.GetNameRegEntry(name)
-	validateEntry(t, entry, name, data, privAccounts[1].Address, state.LastBlockHeight+numDesiredBlocks)
+	validateEntry(t, entry, name, data, testPrivAccounts[1].Address(), blockchain.LastBlockHeight()+numDesiredBlocks)
 
 	// test removal
 	amt = fee
 	data = ""
-	tx, _ = txs.NewNameTx(state, privAccounts[1].PubKey, name, data, amt, fee)
-	tx.Sign(state.ChainID, privAccounts[1])
-	if err := execTxWithStateNewBlock(state, tx, true); err != nil {
+	tx, _ = txs.NewNameTx(state, testPrivAccounts[1].PublicKey(), name, data, amt, fee)
+	tx.Sign(testChainID, testPrivAccounts[1])
+	if err := execTxWithStateNewBlock(state, blockchain, tx); err != nil {
 		t.Fatal(err)
 	}
 	entry = state.GetNameRegEntry(name)
@@ -375,21 +421,24 @@ func TestNameTxs(t *testing.T) {
 	// test removal by key1 after expiry
 	name = "looking_good/karaoke_bar"
 	data = "some data"
-	amt = fee + int64(numDesiredBlocks)*txs.NameByteCostMultiplier*txs.NameBlockCostMultiplier*txs.NameBaseCost(name, data)
-	tx, _ = txs.NewNameTx(state, privAccounts[0].PubKey, name, data, amt, fee)
-	tx.Sign(state.ChainID, privAccounts[0])
-	if err := execTxWithState(state, tx, true); err != nil {
+	amt = fee + numDesiredBlocks*txs.NameByteCostMultiplier*txs.NameBlockCostMultiplier*txs.NameBaseCost(name, data)
+	tx, _ = txs.NewNameTx(state, testPrivAccounts[0].PublicKey(), name, data, amt, fee)
+	tx.Sign(testChainID, testPrivAccounts[0])
+	if err := execTxWithStateAndBlockchain(state, blockchain, tx); err != nil {
 		t.Fatal(err)
 	}
 	entry = state.GetNameRegEntry(name)
-	validateEntry(t, entry, name, data, privAccounts[0].Address, state.LastBlockHeight+numDesiredBlocks)
-	state.LastBlockHeight = entry.Expires
+	validateEntry(t, entry, name, data, testPrivAccounts[0].Address(), blockchain.LastBlockHeight()+numDesiredBlocks)
+	// Fast forward
+	for blockchain.Tip().LastBlockHeight() < entry.Expires {
+		commitNewBlock(state, blockchain)
+	}
 
 	amt = fee
 	data = ""
-	tx, _ = txs.NewNameTx(state, privAccounts[1].PubKey, name, data, amt, fee)
-	tx.Sign(state.ChainID, privAccounts[1])
-	if err := execTxWithStateNewBlock(state, tx, true); err != nil {
+	tx, _ = txs.NewNameTx(state, testPrivAccounts[1].PublicKey(), name, data, amt, fee)
+	tx.Sign(testChainID, testPrivAccounts[1])
+	if err := execTxWithStateNewBlock(state, blockchain, tx); err != nil {
 		t.Fatal(err)
 	}
 	entry = state.GetNameRegEntry(name)
@@ -424,71 +473,71 @@ var createData, _ = hex.DecodeString("9ed93318")
 
 func TestCreates(t *testing.T) {
 	//evm.SetDebug(true)
-	state, privAccounts, _ := RandGenesisState(3, true, 1000, 1, true, 1000)
+	state, privAccounts := makeGenesisState(3, true, 1000, 1, true, 1000)
 
-	//val0 := state.GetValidatorInfo(privValidators[0].Address)
-	acc0 := state.GetAccount(privAccounts[0].PubKey.Address())
-	acc0PubKey := privAccounts[0].PubKey
-	acc1 := state.GetAccount(privAccounts[1].PubKey.Address())
-	acc2 := state.GetAccount(privAccounts[2].PubKey.Address())
+	//val0 := state.GetValidatorInfo(privValidators[0].Address())
+	acc0 := getAccount(state, privAccounts[0].Address())
+	acc0PubKey := privAccounts[0].PublicKey()
+	acc1 := getAccount(state, privAccounts[1].Address())
+	acc2 := getAccount(state, privAccounts[2].Address())
 
 	state = state.Copy()
-	newAcc1 := state.GetAccount(acc1.Address)
-	newAcc1.Code = preFactoryCode
-	newAcc2 := state.GetAccount(acc2.Address)
-	newAcc2.Code = factoryCode
+	newAcc1 := getAccount(state, acc1.Address())
+	newAcc1.SetCode(preFactoryCode)
+	newAcc2 := getAccount(state, acc2.Address())
+	newAcc2.SetCode(factoryCode)
 
 	state.UpdateAccount(newAcc1)
 	state.UpdateAccount(newAcc2)
 
-	createData = append(createData, word256.LeftPadBytes(acc2.Address, 32)...)
+	createData = append(createData, acc2.Address().Word256().Bytes()...)
 
 	// call the pre-factory, triggering the factory to run a create
 	tx := &txs.CallTx{
 		Input: &txs.TxInput{
-			Address:  acc0.Address,
+			Address:  acc0.Address(),
 			Amount:   1,
-			Sequence: acc0.Sequence + 1,
+			Sequence: acc0.Sequence() + 1,
 			PubKey:   acc0PubKey,
 		},
-		Address:  acc1.Address,
+		Address:  addressPtr(acc1),
 		GasLimit: 10000,
 		Data:     createData,
 	}
 
-	tx.Input.Signature = privAccounts[0].Sign(state.ChainID, tx)
-	err := execTxWithState(state, tx, true)
+	tx.Input.Signature = acm.ChainSign(privAccounts[0], testChainID, tx)
+	err := execTxWithState(state, tx)
 	if err != nil {
 		t.Errorf("Got error in executing call transaction, %v", err)
 	}
 
-	acc1 = state.GetAccount(acc1.Address)
-	storage := state.LoadStorage(acc1.StorageRoot)
-	_, firstCreatedAddress, _ := storage.Get(word256.LeftPadBytes([]byte{0}, 32))
+	acc1 = getAccount(state, acc1.Address())
+	storage := state.LoadStorage(acc1.StorageRoot())
+	_, firstCreatedAddress, _ := storage.Get(binary.LeftPadBytes([]byte{0}, 32))
 
-	acc0 = state.GetAccount(acc0.Address)
+	acc0 = getAccount(state, acc0.Address())
 	// call the pre-factory, triggering the factory to run a create
 	tx = &txs.CallTx{
 		Input: &txs.TxInput{
-			Address:  acc0.Address,
+			Address:  acc0.Address(),
 			Amount:   1,
-			Sequence: acc0.Sequence + 1,
+			Sequence: acc0.Sequence() + 1,
 			PubKey:   acc0PubKey,
 		},
-		Address:  acc1.Address,
+		Address:  addressPtr(acc1),
 		GasLimit: 100000,
 		Data:     createData,
 	}
 
-	tx.Input.Signature = privAccounts[0].Sign(state.ChainID, tx)
-	err = execTxWithState(state, tx, true)
+	tx.Input.Signature = acm.ChainSign(privAccounts[0], testChainID, tx)
+	err = execTxWithState(state, tx)
 	if err != nil {
 		t.Errorf("Got error in executing call transaction, %v", err)
 	}
 
-	acc1 = state.GetAccount(acc1.Address)
-	storage = state.LoadStorage(acc1.StorageRoot)
-	_, secondCreatedAddress, _ := storage.Get(word256.LeftPadBytes([]byte{0}, 32))
+	acc1 = getAccount(state, acc1.Address())
+	storage = state.LoadStorage(acc1.StorageRoot())
+	_, secondCreatedAddress, _ := storage.Get(binary.LeftPadBytes([]byte{0}, 32))
 
 	if bytes.Equal(firstCreatedAddress, secondCreatedAddress) {
 		t.Errorf("Multiple contracts created with the same address!")
@@ -506,129 +555,196 @@ var callerCode, _ = hex.DecodeString("60606040526000357c010000000000000000000000
 var sendData, _ = hex.DecodeString("3e58c58c")
 
 func TestContractSend(t *testing.T) {
-	state, privAccounts, _ := RandGenesisState(3, true, 1000, 1, true, 1000)
+	state, privAccounts := makeGenesisState(3, true, 1000, 1, true, 1000)
 
-	//val0 := state.GetValidatorInfo(privValidators[0].Address)
-	acc0 := state.GetAccount(privAccounts[0].PubKey.Address())
-	acc0PubKey := privAccounts[0].PubKey
-	acc1 := state.GetAccount(privAccounts[1].PubKey.Address())
-	acc2 := state.GetAccount(privAccounts[2].PubKey.Address())
+	//val0 := state.GetValidatorInfo(privValidators[0].Address())
+	acc0 := getAccount(state, privAccounts[0].Address())
+	acc0PubKey := privAccounts[0].PublicKey()
+	acc1 := getAccount(state, privAccounts[1].Address())
+	acc2 := getAccount(state, privAccounts[2].Address())
 
 	state = state.Copy()
-	newAcc1 := state.GetAccount(acc1.Address)
-	newAcc1.Code = callerCode
+	newAcc1 := getAccount(state, acc1.Address())
+	newAcc1.SetCode(callerCode)
 	state.UpdateAccount(newAcc1)
 
-	sendData = append(sendData, word256.LeftPadBytes(acc2.Address, 32)...)
-	sendAmt := int64(10)
-	acc2Balance := acc2.Balance
+	sendData = append(sendData, acc2.Address().Word256().Bytes()...)
+	sendAmt := uint64(10)
+	acc2Balance := acc2.Balance()
 
 	// call the contract, triggering the send
 	tx := &txs.CallTx{
 		Input: &txs.TxInput{
-			Address:  acc0.Address,
+			Address:  acc0.Address(),
 			Amount:   sendAmt,
-			Sequence: acc0.Sequence + 1,
+			Sequence: acc0.Sequence() + 1,
 			PubKey:   acc0PubKey,
 		},
-		Address:  acc1.Address,
+		Address:  addressPtr(acc1),
 		GasLimit: 1000,
 		Data:     sendData,
 	}
 
-	tx.Input.Signature = privAccounts[0].Sign(state.ChainID, tx)
-	err := execTxWithState(state, tx, true)
+	tx.Input.Signature = acm.ChainSign(privAccounts[0], testChainID, tx)
+	err := execTxWithState(state, tx)
 	if err != nil {
 		t.Errorf("Got error in executing call transaction, %v", err)
 	}
 
-	acc2 = state.GetAccount(acc2.Address)
-	if acc2.Balance != sendAmt+acc2Balance {
-		t.Errorf("Value transfer from contract failed! Got %d, expected %d", acc2.Balance, sendAmt+acc2Balance)
+	acc2 = getAccount(state, acc2.Address())
+	if acc2.Balance() != sendAmt+acc2Balance {
+		t.Errorf("Value transfer from contract failed! Got %d, expected %d", acc2.Balance(), sendAmt+acc2Balance)
+	}
+}
+func TestMerklePanic(t *testing.T) {
+	state, privAccounts := makeGenesisState(3, true, 1000, 1, true,
+		1000)
+
+	//val0 := state.GetValidatorInfo(privValidators[0].Address())
+	acc0 := getAccount(state, privAccounts[0].Address())
+	acc0PubKey := privAccounts[0].PublicKey()
+	acc1 := getAccount(state, privAccounts[1].Address())
+
+	state.Save()
+	// SendTx.
+	{
+		stateSendTx := state.Copy()
+		tx := &txs.SendTx{
+			Inputs: []*txs.TxInput{
+				{
+					Address:  acc0.Address(),
+					Amount:   1,
+					Sequence: acc0.Sequence() + 1,
+					PubKey:   acc0PubKey,
+				},
+			},
+			Outputs: []*txs.TxOutput{
+				{
+					Address: acc1.Address(),
+					Amount:  1,
+				},
+			},
+		}
+
+		tx.Inputs[0].Signature = acm.ChainSign(privAccounts[0], testChainID, tx)
+		err := execTxWithState(stateSendTx, tx)
+		if err != nil {
+			t.Errorf("Got error in executing send transaction, %v", err)
+		}
+		// uncomment for panic fun!
+		//stateSendTx.Save()
+	}
+
+	// CallTx. Just runs through it and checks the transfer. See vm, rpc tests for more
+	{
+		stateCallTx := state.Copy()
+		newAcc1 := getAccount(stateCallTx, acc1.Address())
+		newAcc1.SetCode([]byte{0x60})
+		stateCallTx.UpdateAccount(newAcc1)
+		tx := &txs.CallTx{
+			Input: &txs.TxInput{
+				Address:  acc0.Address(),
+				Amount:   1,
+				Sequence: acc0.Sequence() + 1,
+				PubKey:   acc0PubKey,
+			},
+			Address:  addressPtr(acc1),
+			GasLimit: 10,
+		}
+
+		tx.Input.Signature = acm.ChainSign(privAccounts[0], testChainID, tx)
+		err := execTxWithState(stateCallTx, tx)
+		if err != nil {
+			t.Errorf("Got error in executing call transaction, %v", err)
+		}
 	}
+	state.Save()
+	trygetacc0 := getAccount(state, privAccounts[0].Address())
+	fmt.Println(trygetacc0.Address())
 }
 
 // TODO: test overflows.
 // TODO: test for unbonding validators.
 func TestTxs(t *testing.T) {
+	state, privAccounts := makeGenesisState(3, true, 1000, 1, true, 1000)
 
-	state, privAccounts, _ := RandGenesisState(3, true, 1000, 1, true, 1000)
-
-	//val0 := state.GetValidatorInfo(privValidators[0].Address)
-	acc0 := state.GetAccount(privAccounts[0].PubKey.Address())
-	acc0PubKey := privAccounts[0].PubKey
-	acc1 := state.GetAccount(privAccounts[1].PubKey.Address())
+	//val0 := state.GetValidatorInfo(privValidators[0].Address())
+	acc0 := getAccount(state, privAccounts[0].Address())
+	acc0PubKey := privAccounts[0].PublicKey()
+	acc1 := getAccount(state, privAccounts[1].Address())
 
 	// SendTx.
 	{
-		state := state.Copy()
+		stateSendTx := state.Copy()
 		tx := &txs.SendTx{
 			Inputs: []*txs.TxInput{
-				&txs.TxInput{
-					Address:  acc0.Address,
+				{
+					Address:  acc0.Address(),
 					Amount:   1,
-					Sequence: acc0.Sequence + 1,
+					Sequence: acc0.Sequence() + 1,
 					PubKey:   acc0PubKey,
 				},
 			},
 			Outputs: []*txs.TxOutput{
-				&txs.TxOutput{
-					Address: acc1.Address,
+				{
+					Address: acc1.Address(),
 					Amount:  1,
 				},
 			},
 		}
 
-		tx.Inputs[0].Signature = privAccounts[0].Sign(state.ChainID, tx)
-		err := execTxWithState(state, tx, true)
+		tx.Inputs[0].Signature = acm.ChainSign(privAccounts[0], testChainID, tx)
+		err := execTxWithState(stateSendTx, tx)
 		if err != nil {
 			t.Errorf("Got error in executing send transaction, %v", err)
 		}
-		newAcc0 := state.GetAccount(acc0.Address)
-		if acc0.Balance-1 != newAcc0.Balance {
+		newAcc0 := getAccount(stateSendTx, acc0.Address())
+		if acc0.Balance()-1 != newAcc0.Balance() {
 			t.Errorf("Unexpected newAcc0 balance. Expected %v, got %v",
-				acc0.Balance-1, newAcc0.Balance)
+				acc0.Balance()-1, newAcc0.Balance())
 		}
-		newAcc1 := state.GetAccount(acc1.Address)
-		if acc1.Balance+1 != newAcc1.Balance {
+		newAcc1 := getAccount(stateSendTx, acc1.Address())
+		if acc1.Balance()+1 != newAcc1.Balance() {
 			t.Errorf("Unexpected newAcc1 balance. Expected %v, got %v",
-				acc1.Balance+1, newAcc1.Balance)
+				acc1.Balance()+1, newAcc1.Balance())
 		}
 	}
 
 	// CallTx. Just runs through it and checks the transfer. See vm, rpc tests for more
 	{
-		state := state.Copy()
-		newAcc1 := state.GetAccount(acc1.Address)
-		newAcc1.Code = []byte{0x60}
-		state.UpdateAccount(newAcc1)
+		stateCallTx := state.Copy()
+		newAcc1 := getAccount(stateCallTx, acc1.Address())
+		newAcc1.SetCode([]byte{0x60})
+		stateCallTx.UpdateAccount(newAcc1)
 		tx := &txs.CallTx{
 			Input: &txs.TxInput{
-				Address:  acc0.Address,
+				Address:  acc0.Address(),
 				Amount:   1,
-				Sequence: acc0.Sequence + 1,
+				Sequence: acc0.Sequence() + 1,
 				PubKey:   acc0PubKey,
 			},
-			Address:  acc1.Address,
+			Address:  addressPtr(acc1),
 			GasLimit: 10,
 		}
 
-		tx.Input.Signature = privAccounts[0].Sign(state.ChainID, tx)
-		err := execTxWithState(state, tx, true)
+		tx.Input.Signature = acm.ChainSign(privAccounts[0], testChainID, tx)
+		err := execTxWithState(stateCallTx, tx)
 		if err != nil {
 			t.Errorf("Got error in executing call transaction, %v", err)
 		}
-		newAcc0 := state.GetAccount(acc0.Address)
-		if acc0.Balance-1 != newAcc0.Balance {
+		newAcc0 := getAccount(stateCallTx, acc0.Address())
+		if acc0.Balance()-1 != newAcc0.Balance() {
 			t.Errorf("Unexpected newAcc0 balance. Expected %v, got %v",
-				acc0.Balance-1, newAcc0.Balance)
+				acc0.Balance()-1, newAcc0.Balance())
 		}
-		newAcc1 = state.GetAccount(acc1.Address)
-		if acc1.Balance+1 != newAcc1.Balance {
+		newAcc1 = getAccount(stateCallTx, acc1.Address())
+		if acc1.Balance()+1 != newAcc1.Balance() {
 			t.Errorf("Unexpected newAcc1 balance. Expected %v, got %v",
-				acc1.Balance+1, newAcc1.Balance)
+				acc1.Balance()+1, newAcc1.Balance())
 		}
 	}
+	trygetacc0 := getAccount(state, privAccounts[0].Address())
+	fmt.Println(trygetacc0.Address())
 
 	// NameTx.
 	{
@@ -648,31 +764,32 @@ attack the network, they'll generate the longest chain and outpace attackers.
 network itself requires minimal structure.   Messages are broadcast on a best effort
 basis,   and   nodes   can   leave  and   rejoin   the  network   at  will,  accepting   the   longest
 proof-of-work chain as proof of what happened while they were gone `
-		entryAmount := int64(10000)
+		entryAmount := uint64(10000)
 
-		state := state.Copy()
+		stateNameTx := state.Copy()
 		tx := &txs.NameTx{
 			Input: &txs.TxInput{
-				Address:  acc0.Address,
+				Address:  acc0.Address(),
 				Amount:   entryAmount,
-				Sequence: acc0.Sequence + 1,
+				Sequence: acc0.Sequence() + 1,
 				PubKey:   acc0PubKey,
 			},
 			Name: entryName,
 			Data: entryData,
 		}
 
-		tx.Input.Signature = privAccounts[0].Sign(state.ChainID, tx)
-		err := execTxWithState(state, tx, true)
+		tx.Input.Signature = acm.ChainSign(privAccounts[0], testChainID, tx)
+
+		err := execTxWithState(stateNameTx, tx)
 		if err != nil {
 			t.Errorf("Got error in executing call transaction, %v", err)
 		}
-		newAcc0 := state.GetAccount(acc0.Address)
-		if acc0.Balance-entryAmount != newAcc0.Balance {
+		newAcc0 := getAccount(stateNameTx, acc0.Address())
+		if acc0.Balance()-entryAmount != newAcc0.Balance() {
 			t.Errorf("Unexpected newAcc0 balance. Expected %v, got %v",
-				acc0.Balance-entryAmount, newAcc0.Balance)
+				acc0.Balance()-entryAmount, newAcc0.Balance())
 		}
-		entry := state.GetNameRegEntry(entryName)
+		entry := stateNameTx.GetNameRegEntry(entryName)
 		if entry == nil {
 			t.Errorf("Expected an entry but got nil")
 		}
@@ -683,8 +800,8 @@ proof-of-work chain as proof of what happened while they were gone `
 		// test a bad string
 		tx.Data = string([]byte{0, 1, 2, 3, 127, 128, 129, 200, 251})
 		tx.Input.Sequence += 1
-		tx.Input.Signature = privAccounts[0].Sign(state.ChainID, tx)
-		err = execTxWithState(state, tx, true)
+		tx.Input.Signature = acm.ChainSign(privAccounts[0], testChainID, tx)
+		err = execTxWithState(stateNameTx, tx)
 		if _, ok := err.(txs.ErrTxInvalidString); !ok {
 			t.Errorf("Expected invalid string error. Got: %s", err.Error())
 		}
@@ -695,44 +812,44 @@ proof-of-work chain as proof of what happened while they were gone `
 		{
 			state := state.Copy()
 			tx := &txs.BondTx{
-				PubKey: acc0PubKey.(crypto.PubKeyEd25519),
+				PublicKey: acc0PubKey.(acm.PublicKeyEd25519),
 				Inputs: []*txs.TxInput{
 					&txs.TxInput{
-						Address:  acc0.Address,
+						Address:  acc0.Address(),
 						Amount:   1,
-						Sequence: acc0.Sequence + 1,
-						PubKey:   acc0PubKey,
+						Sequence: acc0.Sequence() + 1,
+						PublicKey:   acc0PubKey,
 					},
 				},
 				UnbondTo: []*txs.TxOutput{
 					&txs.TxOutput{
-						Address: acc0.Address,
+						Address: acc0.Address(),
 						Amount:  1,
 					},
 				},
 			}
-			tx.Signature = privAccounts[0].Sign(state.ChainID, tx).(crypto.SignatureEd25519)
-			tx.Inputs[0].Signature = privAccounts[0].Sign(state.ChainID, tx)
-			err := execTxWithState(state, tx, true)
+			tx.Signature = privAccounts[0] acm.ChainSign(testChainID, tx).(crypto.SignatureEd25519)
+			tx.Inputs[0].Signature = privAccounts[0] acm.ChainSign(testChainID, tx)
+			err := execTxWithState(state, tx)
 			if err != nil {
 				t.Errorf("Got error in executing bond transaction, %v", err)
 			}
-			newAcc0 := state.GetAccount(acc0.Address)
-			if newAcc0.Balance != acc0.Balance-1 {
+			newAcc0 := getAccount(state, acc0.Address())
+			if newAcc0.Balance() != acc0.Balance()-1 {
 				t.Errorf("Unexpected newAcc0 balance. Expected %v, got %v",
-					acc0.Balance-1, newAcc0.Balance)
+					acc0.Balance()-1, newAcc0.Balance())
 			}
-			_, acc0Val := state.BondedValidators.GetByAddress(acc0.Address)
+			_, acc0Val := state.BondedValidators.GetByAddress(acc0.Address())
 			if acc0Val == nil {
 				t.Errorf("acc0Val not present")
 			}
-			if acc0Val.BondHeight != state.LastBlockHeight+1 {
+			if acc0Val.BondHeight != blockchain.LastBlockHeight()+1 {
 				t.Errorf("Unexpected bond height. Expected %v, got %v",
-					state.LastBlockHeight, acc0Val.BondHeight)
+					blockchain.LastBlockHeight(), acc0Val.BondHeight)
 			}
 			if acc0Val.VotingPower != 1 {
 				t.Errorf("Unexpected voting power. Expected %v, got %v",
-					acc0Val.VotingPower, acc0.Balance)
+					acc0Val.VotingPower, acc0.Balance())
 			}
 			if acc0Val.Accum != 0 {
 				t.Errorf("Unexpected accum. Expected 0, got %v",
@@ -746,52 +863,52 @@ proof-of-work chain as proof of what happened while they were gone `
 
 func TestSelfDestruct(t *testing.T) {
 
-	state, privAccounts, _ := RandGenesisState(3, true, 1000, 1, true, 1000)
+	state, privAccounts := makeGenesisState(3, true, 1000, 1, true, 1000)
 
-	acc0 := state.GetAccount(privAccounts[0].PubKey.Address())
-	acc0PubKey := privAccounts[0].PubKey
-	acc1 := state.GetAccount(privAccounts[1].PubKey.Address())
-	acc2 := state.GetAccount(privAccounts[2].Address)
-	sendingAmount, refundedBalance, oldBalance := int64(1), acc1.Balance, acc2.Balance
+	acc0 := getAccount(state, privAccounts[0].Address())
+	acc0PubKey := privAccounts[0].PublicKey()
+	acc1 := getAccount(state, privAccounts[1].Address())
+	acc2 := getAccount(state, privAccounts[2].Address())
+	sendingAmount, refundedBalance, oldBalance := uint64(1), acc1.Balance(), acc2.Balance()
 
-	newAcc1 := state.GetAccount(acc1.Address)
+	newAcc1 := getAccount(state, acc1.Address())
 
 	// store 0x1 at 0x1, push an address, then self-destruct:)
 	contractCode := []byte{0x60, 0x01, 0x60, 0x01, 0x55, 0x73}
-	contractCode = append(contractCode, acc2.Address...)
+	contractCode = append(contractCode, acc2.Address().Bytes()...)
 	contractCode = append(contractCode, 0xff)
-	newAcc1.Code = contractCode
+	newAcc1.SetCode(contractCode)
 	state.UpdateAccount(newAcc1)
 
 	// send call tx with no data, cause self-destruct
-	tx := txs.NewCallTxWithNonce(acc0PubKey, acc1.Address, nil, sendingAmount, 1000, 0, acc0.Sequence+1)
-	tx.Input.Signature = privAccounts[0].Sign(state.ChainID, tx)
+	tx := txs.NewCallTxWithNonce(acc0PubKey, addressPtr(acc1), nil, sendingAmount, 1000, 0, acc0.Sequence()+1)
+	tx.Input.Signature = acm.ChainSign(privAccounts[0], testChainID, tx)
 
 	// we use cache instead of execTxWithState so we can run the tx twice
-	cache := NewBlockCache(state)
-	if err := ExecTx(cache, tx, true, nil, logger); err != nil {
+	exe := NewBatchCommitter(state, testChainID, bcm.NewBlockchain(testGenesisDoc), event.NewNoOpFireable(), logger)
+	if err := exe.Execute(tx); err != nil {
 		t.Errorf("Got error in executing call transaction, %v", err)
 	}
 
 	// if we do it again, we won't get an error, but the self-destruct
 	// shouldn't happen twice and the caller should lose fee
 	tx.Input.Sequence += 1
-	tx.Input.Signature = privAccounts[0].Sign(state.ChainID, tx)
-	if err := ExecTx(cache, tx, true, nil, logger); err != nil {
+	tx.Input.Signature = acm.ChainSign(privAccounts[0], testChainID, tx)
+	if err := exe.Execute(tx); err != nil {
 		t.Errorf("Got error in executing call transaction, %v", err)
 	}
 
 	// commit the block
-	cache.Sync()
+	exe.Commit()
 
 	// acc2 should receive the sent funds and the contracts balance
-	newAcc2 := state.GetAccount(acc2.Address)
+	newAcc2 := getAccount(state, acc2.Address())
 	newBalance := sendingAmount + refundedBalance + oldBalance
-	if newAcc2.Balance != newBalance {
+	if newAcc2.Balance() != newBalance {
 		t.Errorf("Unexpected newAcc2 balance. Expected %v, got %v",
-			newAcc2.Balance, newBalance)
+			newAcc2.Balance(), newBalance)
 	}
-	newAcc1 = state.GetAccount(acc1.Address)
+	newAcc1 = getAccount(state, acc1.Address())
 	if newAcc1 != nil {
 		t.Errorf("Expected account to be removed")
 	}
@@ -802,29 +919,29 @@ func TestSelfDestruct(t *testing.T) {
 func TestAddValidator(t *testing.T) {
 
 	// Generate a state, save & load it.
-	s0, privAccounts, privValidators := RandGenesisState(10, false, 1000, 1, false, 1000)
+	s0, privAccounts, privValidators := makeGenesisState(10, false, 1000, 1, false, 1000)
 
 	// The first privAccount will become a validator
 	acc0 := privAccounts[0]
 	bondTx := &txs.BondTx{
-		PubKey: acc0.PubKey.(account.PubKeyEd25519),
+		PublicKey: acc0.PublicKey.(account.PubKeyEd25519),
 		Inputs: []*txs.TxInput{
 			&txs.TxInput{
-				Address:  acc0.Address,
+				Address:  acc0.Address(),
 				Amount:   1000,
 				Sequence: 1,
-				PubKey:   acc0.PubKey,
+				PublicKey:   acc0.PublicKey,
 			},
 		},
 		UnbondTo: []*txs.TxOutput{
 			&txs.TxOutput{
-				Address: acc0.Address,
+				Address: acc0.Address(),
 				Amount:  1000,
 			},
 		},
 	}
-	bondTx.Signature = acc0.Sign(s0.ChainID, bondTx).(account.SignatureEd25519)
-	bondTx.Inputs[0].Signature = acc0.Sign(s0.ChainID, bondTx)
+	bondTx.Signature = acc0 acm.ChainSign(testChainID, bondTx).(account.SignatureEd25519)
+	bondTx.Inputs[0].Signature = acc0 acm.ChainSign(testChainID, bondTx)
 
 	// Make complete block and blockParts
 	block0 := makeBlock(t, s0, nil, []txs.Tx{bondTx})
@@ -858,7 +975,7 @@ func TestAddValidator(t *testing.T) {
 		BlockHash:        block0.Hash(),
 		BlockPartsHeader: block0Parts.Header(),
 	}
-	privValidators[0].SignVote(s0.ChainID, precommit0)
+	privValidators[0].SignVote(testChainID, precommit0)
 
 	block1 := makeBlock(t, s0,
 		&txs.Validation{
diff --git a/execution/transactor.go b/execution/transactor.go
new file mode 100644
index 00000000..e9957310
--- /dev/null
+++ b/execution/transactor.go
@@ -0,0 +1,457 @@
+// 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 execution
+
+import (
+	"bytes"
+	"fmt"
+	"sync"
+	"time"
+
+	"reflect"
+
+	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/binary"
+	"github.com/hyperledger/burrow/blockchain"
+	"github.com/hyperledger/burrow/event"
+	exe_events "github.com/hyperledger/burrow/execution/events"
+	"github.com/hyperledger/burrow/execution/evm"
+	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"
+)
+
+type Call struct {
+	Return  []byte `json:"return"`
+	GasUsed uint64 `json:"gas_used"`
+}
+
+type Transactor interface {
+	Call(fromAddress, toAddress acm.Address, data []byte) (*Call, error)
+	CallCode(fromAddress acm.Address, code, data []byte) (*Call, error)
+	BroadcastTx(tx txs.Tx) (*txs.Receipt, error)
+	BroadcastTxAsync(tx txs.Tx, callback func(res *abci_types.Response)) error
+	Transact(privKey []byte, address acm.Address, data []byte, gasLimit, fee uint64) (*txs.Receipt, error)
+	TransactAndHold(privKey []byte, address acm.Address, data []byte, gasLimit, fee uint64) (*evm_events.EventDataCall, error)
+	Send(privKey []byte, toAddress acm.Address, amount uint64) (*txs.Receipt, error)
+	SendAndHold(privKey []byte, toAddress acm.Address, amount uint64) (*txs.Receipt, error)
+	TransactNameReg(privKey []byte, name, data string, amount, fee uint64) (*txs.Receipt, error)
+	SignTx(tx txs.Tx, privAccounts []acm.PrivateAccount) (txs.Tx, error)
+}
+
+// Transactor is the controller/middleware for the v0 RPC
+type transactor struct {
+	txMtx            *sync.Mutex
+	blockchain       blockchain.Blockchain
+	state            acm.StateReader
+	eventEmitter     event.Emitter
+	broadcastTxAsync func(tx txs.Tx, callback func(res *abci_types.Response)) error
+	logger           logging_types.InfoTraceLogger
+}
+
+var _ Transactor = &transactor{}
+
+func NewTransactor(blockchain blockchain.Blockchain, state acm.StateReader, eventEmitter event.Emitter,
+	broadcastTxAsync func(tx txs.Tx, callback func(res *abci_types.Response)) error,
+	logger logging_types.InfoTraceLogger) *transactor {
+
+	return &transactor{
+		blockchain:       blockchain,
+		state:            state,
+		eventEmitter:     eventEmitter,
+		broadcastTxAsync: broadcastTxAsync,
+		logger:           logger.With(structure.ComponentKey, "Transactor"),
+	}
+}
+
+// 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) {
+	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)
+	if err != nil {
+		return nil, err
+	}
+	if callee == nil {
+		return nil, fmt.Errorf("account %s does not exist", toAddress)
+	}
+	caller := acm.ConcreteAccount{Address: fromAddress}.MutableAccount()
+	txCache := NewTxCache(trans.state)
+	params := vmParams(trans.blockchain)
+
+	vmach := evm.NewVM(txCache, evm.DefaultDynamicMemoryProvider, params, caller.Address(), nil,
+		logging.WithScope(trans.logger, "Call"))
+	vmach.SetFireable(trans.eventEmitter)
+
+	gas := params.GasLimit
+	ret, err := vmach.Call(caller, callee, callee.Code(), data, 0, &gas)
+	if err != nil {
+		return nil, err
+	}
+	gasUsed := params.GasLimit - gas
+	return &Call{Return: ret, GasUsed: gasUsed}, nil
+}
+
+// Run the given code on an isolated and unpersisted state
+// Cannot be used to create new contracts.
+func (trans *transactor) CallCode(fromAddress acm.Address, code, data []byte) (*Call, error) {
+	// 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 := NewTxCache(trans.state)
+	params := vmParams(trans.blockchain)
+
+	vmach := evm.NewVM(txCache, evm.DefaultDynamicMemoryProvider, params, caller.Address(), nil,
+		logging.WithScope(trans.logger, "CallCode"))
+	gas := params.GasLimit
+	ret, err := vmach.Call(caller, callee, code, data, 0, &gas)
+	if err != nil {
+		return nil, err
+	}
+	gasUsed := params.GasLimit - gas
+	return &Call{Return: ret, GasUsed: gasUsed}, nil
+}
+
+func (trans *transactor) BroadcastTxAsync(tx txs.Tx, callback func(res *abci_types.Response)) error {
+	return trans.broadcastTxAsync(tx, callback)
+}
+
+// Broadcast a transaction.
+func (trans *transactor) BroadcastTx(tx txs.Tx) (*txs.Receipt, error) {
+	responseCh := make(chan *abci_types.Response, 1)
+	err := trans.BroadcastTxAsync(tx, func(res *abci_types.Response) {
+		responseCh <- res
+	})
+
+	if err != nil {
+		return nil, err
+	}
+	response := <-responseCh
+	checkTxResponse := response.GetCheckTx()
+	if checkTxResponse == nil {
+		return nil, fmt.Errorf("application did not return CheckTx response")
+	}
+
+	switch checkTxResponse.Code {
+	case abci_types.CodeType_OK:
+		receipt := new(txs.Receipt)
+		err := wire.ReadBinaryBytes(checkTxResponse.Data, receipt)
+		if err != nil {
+			return nil, fmt.Errorf("could not deserialise transaction receipt: %s", err)
+		}
+		return receipt, nil
+	default:
+		return nil, fmt.Errorf("error returned by Tendermint in BroadcastTxSync "+
+			"ABCI code: %v, ABCI log: %v", checkTxResponse.Code, checkTxResponse.Log)
+	}
+}
+
+// Orders calls to BroadcastTx using lock (waits for response from core before releasing)
+func (trans *transactor) Transact(privKey []byte, address acm.Address, data []byte, gasLimit,
+	fee uint64) (*txs.Receipt, error) {
+	if len(privKey) != 64 {
+		return nil, fmt.Errorf("Private key is not of the right length: %d\n", len(privKey))
+	}
+	trans.txMtx.Lock()
+	defer trans.txMtx.Unlock()
+	pa := acm.GeneratePrivateAccountFromPrivateKeyBytes(privKey)
+	// [Silas] This is puzzling, if the account doesn't exist the CallTx will fail, so what's the point in this?
+	acc, err := trans.state.GetAccount(pa.Address())
+	if err != nil {
+		return nil, err
+	}
+	sequence := uint64(1)
+	if acc != nil {
+		sequence = acc.Sequence() + uint64(1)
+	}
+	// TODO: [Silas] we should consider revising this method and removing fee, or
+	// possibly adding an amount parameter. It is non-sensical to just be able to
+	// set the fee. Our support of fees in general is questionable since at the
+	// moment all we do is deduct the fee effectively leaking token. It is possible
+	// someone may be using the sending of native token to payable functions but
+	// they can be served by broadcasting a token.
+
+	// We hard-code the amount to be equal to the fee which means the CallTx we
+	// generate transfers 0 value, which is the most sensible default since in
+	// recent solidity compilers the EVM generated will throw an error if value
+	// is transferred to a non-payable function.
+	txInput := &txs.TxInput{
+		Address:  pa.Address(),
+		Amount:   fee,
+		Sequence: sequence,
+		PubKey:   pa.PublicKey(),
+	}
+	tx := &txs.CallTx{
+		Input:    txInput,
+		Address:  &address,
+		GasLimit: gasLimit,
+		Fee:      fee,
+		Data:     data,
+	}
+
+	// Got ourselves a tx.
+	txS, errS := trans.SignTx(tx, []acm.PrivateAccount{pa})
+	if errS != nil {
+		return nil, errS
+	}
+	return trans.BroadcastTx(txS)
+}
+
+func (trans *transactor) TransactAndHold(privKey []byte, address acm.Address, data []byte, gasLimit,
+	fee uint64) (*evm_events.EventDataCall, error) {
+	rec, tErr := trans.Transact(privKey, address, data, gasLimit, fee)
+	if tErr != nil {
+		return nil, tErr
+	}
+	var addr acm.Address
+	if rec.CreatesContract {
+		addr = rec.ContractAddr
+	} else {
+		addr = address
+	}
+	// We want non-blocking on the first event received (but buffer the value),
+	// after which we want to block (and then discard the value - see below)
+	wc := make(chan *evm_events.EventDataCall, 1)
+	subId := fmt.Sprintf("%X", rec.TxHash)
+	trans.eventEmitter.Subscribe(subId, evm_events.EventStringAccCall(addr),
+		func(eventData event.AnyEventData) {
+			eventDataCall := eventData.EventDataCall()
+			if eventDataCall == nil {
+				trans.logger.Info("error", "cold not be convert event data to EventDataCall",
+					structure.ScopeKey, "TransactAndHold",
+					"sub_id", subId,
+					"event_data_type", reflect.TypeOf(eventData.Get()).String())
+				return
+			}
+			if bytes.Equal(eventDataCall.TxID, rec.TxHash) {
+				// Beware the contract of go-events subscribe is that we must not be
+				// blocking in an event callback when we try to unsubscribe!
+				// We work around this by using a non-blocking send.
+				select {
+				// This is a non-blocking send, but since we are using a buffered
+				// channel of size 1 we will always grab our first event even if we
+				// haven't read from the channel at the time we receive the first event.
+				case wc <- eventDataCall:
+				default:
+				}
+			}
+		})
+
+	timer := time.NewTimer(300 * time.Second)
+	toChan := timer.C
+
+	var ret *evm_events.EventDataCall
+	var rErr error
+
+	select {
+	case <-toChan:
+		rErr = fmt.Errorf("Transaction timed out. Hash: " + subId)
+	case e := <-wc:
+		timer.Stop()
+		if e.Exception != "" {
+			rErr = fmt.Errorf("error when transacting: " + e.Exception)
+		} else {
+			ret = e
+		}
+	}
+	trans.eventEmitter.Unsubscribe(subId)
+	return ret, rErr
+}
+
+func (trans *transactor) Send(privKey []byte, toAddress acm.Address, amount uint64) (*txs.Receipt, error) {
+	if len(privKey) != 64 {
+		return nil, fmt.Errorf("Private key is not of the right length: %d\n",
+			len(privKey))
+	}
+
+	pk := &[64]byte{}
+	copy(pk[:], privKey)
+	trans.txMtx.Lock()
+	defer trans.txMtx.Unlock()
+	pa := acm.GeneratePrivateAccountFromPrivateKeyBytes(privKey)
+	cache := trans.state
+	acc, err := cache.GetAccount(pa.Address())
+	if err != nil {
+		return nil, err
+	}
+	sequence := uint64(1)
+	if acc != nil {
+		sequence = acc.Sequence() + uint64(1)
+	}
+
+	tx := txs.NewSendTx()
+
+	txInput := &txs.TxInput{
+		Address:  pa.Address(),
+		Amount:   amount,
+		Sequence: sequence,
+		PubKey:   pa.PublicKey(),
+	}
+
+	tx.Inputs = append(tx.Inputs, txInput)
+
+	txOutput := &txs.TxOutput{Address: toAddress, Amount: amount}
+
+	tx.Outputs = append(tx.Outputs, txOutput)
+
+	// Got ourselves a tx.
+	txS, errS := trans.SignTx(tx, []acm.PrivateAccount{pa})
+	if errS != nil {
+		return nil, errS
+	}
+	return trans.BroadcastTx(txS)
+}
+
+func (trans *transactor) SendAndHold(privKey []byte, toAddress acm.Address, amount uint64) (*txs.Receipt, error) {
+	rec, tErr := trans.Send(privKey, toAddress, amount)
+	if tErr != nil {
+		return nil, tErr
+	}
+
+	wc := make(chan *txs.SendTx)
+	subId := fmt.Sprintf("%X", rec.TxHash)
+
+	trans.eventEmitter.Subscribe(subId, exe_events.EventStringAccOutput(toAddress),
+		func(eventData event.AnyEventData) {
+			eventDataTx, ok := eventData.Get().(exe_events.EventDataTx)
+			if !ok {
+				trans.logger.Info("error", "cold not be convert event data to EventDataCall",
+					structure.ScopeKey, "SendAndHold",
+					"tx_hash", subId,
+					"event_data_type", reflect.TypeOf(eventData.Get()).String())
+				return
+			}
+			tx, ok := eventDataTx.Tx.(*txs.SendTx)
+			if !ok {
+				trans.logger.Info("error", "EventDataTx was expected to contain SendTx",
+					structure.ScopeKey, "SendAndHold",
+					"sub_id", subId,
+					"tx_type", reflect.TypeOf(eventDataTx.Tx).String())
+				return
+			}
+
+			wc <- tx
+		})
+
+	timer := time.NewTimer(300 * time.Second)
+	toChan := timer.C
+
+	var rErr error
+
+	pa := acm.GeneratePrivateAccountFromPrivateKeyBytes(privKey)
+
+	select {
+	case <-toChan:
+		rErr = fmt.Errorf("Transaction timed out. Hash: " + subId)
+	case e := <-wc:
+		if e.Inputs[0].Address == pa.Address() && e.Inputs[0].Amount == amount {
+			timer.Stop()
+			trans.eventEmitter.Unsubscribe(subId)
+			return rec, rErr
+		}
+	}
+	return nil, rErr
+}
+
+func (trans *transactor) TransactNameReg(privKey []byte, name, data string, amount, fee uint64) (*txs.Receipt, error) {
+
+	if len(privKey) != 64 {
+		return nil, fmt.Errorf("Private key is not of the right length: %d\n", len(privKey))
+	}
+	trans.txMtx.Lock()
+	defer trans.txMtx.Unlock()
+	pa := acm.GeneratePrivateAccountFromPrivateKeyBytes(privKey)
+	cache := trans.state // XXX: DON'T MUTATE THIS CACHE (used internally for CheckTx)
+	acc, err := cache.GetAccount(pa.Address())
+	if err != nil {
+		return nil, err
+	}
+	sequence := uint64(1)
+	if acc == nil {
+		sequence = acc.Sequence() + uint64(1)
+	}
+	tx := txs.NewNameTxWithNonce(pa.PublicKey(), name, data, amount, fee, sequence)
+	// Got ourselves a tx.
+	txS, errS := trans.SignTx(tx, []acm.PrivateAccount{pa})
+	if errS != nil {
+		return nil, errS
+	}
+	return trans.BroadcastTx(txS)
+}
+
+// Sign a transaction
+func (trans *transactor) SignTx(tx txs.Tx, privAccounts []acm.PrivateAccount) (txs.Tx, error) {
+	// more checks?
+
+	for i, privAccount := range privAccounts {
+		if privAccount == nil || privAccount.PrivateKey().Unwrap() == nil {
+			return nil, fmt.Errorf("invalid (empty) privAccount @%v", i)
+		}
+	}
+	chainID := trans.blockchain.ChainID()
+	switch tx.(type) {
+	case *txs.NameTx:
+		nameTx := tx.(*txs.NameTx)
+		nameTx.Input.PubKey = privAccounts[0].PublicKey()
+		nameTx.Input.Signature = acm.ChainSign(privAccounts[0], chainID, nameTx)
+	case *txs.SendTx:
+		sendTx := tx.(*txs.SendTx)
+		for i, input := range sendTx.Inputs {
+			input.PubKey = privAccounts[i].PublicKey()
+			input.Signature = acm.ChainSign(privAccounts[i], chainID, sendTx)
+		}
+	case *txs.CallTx:
+		callTx := tx.(*txs.CallTx)
+		callTx.Input.PubKey = privAccounts[0].PublicKey()
+		callTx.Input.Signature = acm.ChainSign(privAccounts[0], chainID, callTx)
+	case *txs.BondTx:
+		bondTx := tx.(*txs.BondTx)
+		// the first privaccount corresponds to the BondTx pub key.
+		// the rest to the inputs
+		bondTx.Signature = acm.ChainSign(privAccounts[0], chainID, bondTx)
+		for i, input := range bondTx.Inputs {
+			input.PubKey = privAccounts[i+1].PublicKey()
+			input.Signature = acm.ChainSign(privAccounts[i+1], chainID, bondTx)
+		}
+	case *txs.UnbondTx:
+		unbondTx := tx.(*txs.UnbondTx)
+		unbondTx.Signature = acm.ChainSign(privAccounts[0], chainID, unbondTx)
+	case *txs.RebondTx:
+		rebondTx := tx.(*txs.RebondTx)
+		rebondTx.Signature = acm.ChainSign(privAccounts[0], chainID, rebondTx)
+	default:
+		return nil, fmt.Errorf("Object is not a proper transaction: %v\n", tx)
+	}
+	return tx, nil
+}
+
+func vmParams(blockchain blockchain.Blockchain) evm.Params {
+	tip := blockchain.Tip()
+	return evm.Params{
+		BlockHeight: tip.LastBlockHeight(),
+		BlockHash:   binary.LeftPadWord256(tip.LastBlockHash()),
+		BlockTime:   tip.LastBlockTime().Unix(),
+		GasLimit:    GasLimit,
+	}
+}
diff --git a/execution/tx_cache.go b/execution/tx_cache.go
new file mode 100644
index 00000000..4dc56485
--- /dev/null
+++ b/execution/tx_cache.go
@@ -0,0 +1,128 @@
+// 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 execution
+
+import (
+	"fmt"
+
+	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/binary"
+)
+
+type TxCache struct {
+	backend  acm.StateReader
+	accounts map[acm.Address]vmAccountInfo
+	storages map[binary.Tuple256]binary.Word256
+}
+
+var _ acm.StateWriter = &TxCache{}
+
+func NewTxCache(backend acm.StateReader) *TxCache {
+	return &TxCache{
+		backend:  backend,
+		accounts: make(map[acm.Address]vmAccountInfo),
+		storages: make(map[binary.Tuple256]binary.Word256),
+	}
+}
+
+//-------------------------------------
+// TxCache.account
+
+func (cache *TxCache) GetAccount(addr acm.Address) (acm.Account, error) {
+	acc, removed := cache.accounts[addr].unpack()
+	if removed {
+		return nil, nil
+	} else if acc == nil {
+		return cache.backend.GetAccount(addr)
+	}
+	return acc, nil
+}
+
+func (cache *TxCache) UpdateAccount(acc acm.Account) error {
+	_, removed := cache.accounts[acc.Address()].unpack()
+	if removed {
+		return fmt.Errorf("UpdateAccount on a removed account %s", acc.Address())
+	}
+	cache.accounts[acc.Address()] = vmAccountInfo{acc, false}
+	return nil
+}
+
+func (cache *TxCache) RemoveAccount(addr acm.Address) error {
+	acc, removed := cache.accounts[addr].unpack()
+	if removed {
+		fmt.Errorf("RemoveAccount on a removed account %s", addr)
+	}
+	cache.accounts[addr] = vmAccountInfo{acc, true}
+	return nil
+}
+
+// TxCache.account
+//-------------------------------------
+// TxCache.storage
+
+func (cache *TxCache) GetStorage(addr acm.Address, key binary.Word256) (binary.Word256, error) {
+	// Check cache
+	value, ok := cache.storages[binary.Tuple256{First: addr.Word256(), Second: key}]
+	if ok {
+		return value, nil
+	}
+
+	// Load from backend
+	return cache.backend.GetStorage(addr, key)
+}
+
+// NOTE: Set value to zero to removed from the trie.
+func (cache *TxCache) SetStorage(addr acm.Address, key binary.Word256, value binary.Word256) error {
+	_, removed := cache.accounts[addr].unpack()
+	if removed {
+		fmt.Errorf("SetStorage on a removed account %s", addr)
+	}
+	cache.storages[binary.Tuple256{First: addr.Word256(), Second: key}] = value
+	return nil
+}
+
+// TxCache.storage
+//-------------------------------------
+
+// These updates do not have to be in deterministic order,
+// the backend is responsible for ordering updates.
+func (cache *TxCache) Sync(backend acm.StateWriter) {
+	// Remove or update storage
+	for addrKey, value := range cache.storages {
+		addrWord256, key := binary.Tuple256Split(addrKey)
+		backend.SetStorage(acm.AddressFromWord256(addrWord256), key, value)
+	}
+
+	// Remove or update accounts
+	for addr, accInfo := range cache.accounts {
+		acc, removed := accInfo.unpack()
+		if removed {
+			backend.RemoveAccount(addr)
+		} else {
+			backend.UpdateAccount(acc)
+		}
+	}
+}
+
+//-----------------------------------------------------------------------------
+
+type vmAccountInfo struct {
+	account acm.Account
+	removed bool
+}
+
+func (accInfo vmAccountInfo) unpack() (acm.Account, bool) {
+	return accInfo.account, accInfo.removed
+}
diff --git a/manager/burrow-mint/accounts.go b/manager/burrow-mint/accounts.go
deleted file mode 100644
index b0e58c35..00000000
--- a/manager/burrow-mint/accounts.go
+++ /dev/null
@@ -1,228 +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 burrowmint
-
-// Accounts is part of the pipe for BurrowMint and provides the implementation
-// for the pipe to call into the BurrowMint application
-
-import (
-	"bytes"
-	"encoding/hex"
-	"fmt"
-	"sync"
-
-	account "github.com/hyperledger/burrow/account"
-	core_types "github.com/hyperledger/burrow/core/types"
-	definitions "github.com/hyperledger/burrow/definitions"
-	event "github.com/hyperledger/burrow/event"
-	word256 "github.com/hyperledger/burrow/word256"
-)
-
-// NOTE [ben] Compiler check to ensure Accounts successfully implements
-// burrow/definitions.Accounts
-var _ definitions.Accounts = (*accounts)(nil)
-
-// The accounts struct has methods for working with accounts.
-type accounts struct {
-	burrowMint    *BurrowMint
-	filterFactory *event.FilterFactory
-}
-
-func newAccounts(burrowMint *BurrowMint) *accounts {
-	ff := event.NewFilterFactory()
-
-	ff.RegisterFilterPool("code", &sync.Pool{
-		New: func() interface{} {
-			return &AccountCodeFilter{}
-		},
-	})
-
-	ff.RegisterFilterPool("balance", &sync.Pool{
-		New: func() interface{} {
-			return &AccountBalanceFilter{}
-		},
-	})
-
-	return &accounts{burrowMint, ff}
-
-}
-
-// Generate a new Private Key Account.
-func (this *accounts) GenPrivAccount() (*account.PrivAccount, error) {
-	pa := account.GenPrivAccount()
-	return pa, nil
-}
-
-// Generate a new Private Key Account.
-func (this *accounts) GenPrivAccountFromKey(privKey []byte) (
-	*account.PrivAccount, error) {
-	if len(privKey) != 64 {
-		return nil, fmt.Errorf("Private key is not 64 bytes long.")
-	}
-	fmt.Printf("PK BYTES FROM ACCOUNTS: %x\n", privKey)
-	pa := account.GenPrivAccountFromPrivKeyBytes(privKey)
-	return pa, nil
-}
-
-// Get all accounts.
-func (this *accounts) Accounts(fda []*event.FilterData) (
-	*core_types.AccountList, error) {
-	accounts := make([]*account.Account, 0)
-	state := this.burrowMint.GetState()
-	filter, err := this.filterFactory.NewFilter(fda)
-	if err != nil {
-		return nil, fmt.Errorf("Error in query: " + err.Error())
-	}
-	state.GetAccounts().Iterate(func(key, value []byte) bool {
-		acc := account.DecodeAccount(value)
-		if filter.Match(acc) {
-			accounts = append(accounts, acc)
-		}
-		return false
-	})
-	return &core_types.AccountList{accounts}, nil
-}
-
-// Get an account.
-func (this *accounts) Account(address []byte) (*account.Account, error) {
-	cache := this.burrowMint.GetState() // NOTE: we want to read from mempool!
-	acc := cache.GetAccount(address)
-	if acc == nil {
-		acc = this.newAcc(address)
-	}
-	return acc, nil
-}
-
-// Get the value stored at 'key' in the account with address 'address'
-// Both the key and value is returned.
-func (this *accounts) StorageAt(address, key []byte) (*core_types.StorageItem,
-	error) {
-	state := this.burrowMint.GetState()
-	account := state.GetAccount(address)
-	if account == nil {
-		return &core_types.StorageItem{key, []byte{}}, nil
-	}
-	storageRoot := account.StorageRoot
-	storageTree := state.LoadStorage(storageRoot)
-
-	_, value, _ := storageTree.Get(word256.LeftPadWord256(key).Bytes())
-	if value == nil {
-		return &core_types.StorageItem{key, []byte{}}, nil
-	}
-	return &core_types.StorageItem{key, value}, nil
-}
-
-// Get the storage of the account with address 'address'.
-func (this *accounts) Storage(address []byte) (*core_types.Storage, error) {
-
-	state := this.burrowMint.GetState()
-	account := state.GetAccount(address)
-	storageItems := make([]core_types.StorageItem, 0)
-	if account == nil {
-		return &core_types.Storage{nil, storageItems}, nil
-	}
-	storageRoot := account.StorageRoot
-	storageTree := state.LoadStorage(storageRoot)
-
-	storageTree.Iterate(func(key, value []byte) bool {
-		storageItems = append(storageItems, core_types.StorageItem{
-			key, value})
-		return false
-	})
-	return &core_types.Storage{storageRoot, storageItems}, nil
-}
-
-// Create a new account.
-func (this *accounts) newAcc(address []byte) *account.Account {
-	return &account.Account{
-		Address:     address,
-		PubKey:      nil,
-		Sequence:    0,
-		Balance:     0,
-		Code:        nil,
-		StorageRoot: nil,
-	}
-}
-
-// Filter for account code.
-// Ops: == or !=
-// Could be used to match against nil, to see if an account is a contract account.
-type AccountCodeFilter struct {
-	op    string
-	value []byte
-	match func([]byte, []byte) bool
-}
-
-func (this *AccountCodeFilter) Configure(fd *event.FilterData) error {
-	op := fd.Op
-	val, err := hex.DecodeString(fd.Value)
-
-	if err != nil {
-		return fmt.Errorf("Wrong value type.")
-	}
-	if op == "==" {
-		this.match = func(a, b []byte) bool {
-			return bytes.Equal(a, b)
-		}
-	} else if op == "!=" {
-		this.match = func(a, b []byte) bool {
-			return !bytes.Equal(a, b)
-		}
-	} else {
-		return fmt.Errorf("Op: " + this.op + " is not supported for 'code' filtering")
-	}
-	this.op = op
-	this.value = val
-	return nil
-}
-
-func (this *AccountCodeFilter) Match(v interface{}) bool {
-	acc, ok := v.(*account.Account)
-	if !ok {
-		return false
-	}
-	return this.match(acc.Code, this.value)
-}
-
-// Filter for account balance.
-// Ops: All
-type AccountBalanceFilter struct {
-	op    string
-	value int64
-	match func(int64, int64) bool
-}
-
-func (this *AccountBalanceFilter) Configure(fd *event.FilterData) error {
-	val, err := event.ParseNumberValue(fd.Value)
-	if err != nil {
-		return err
-	}
-	match, err2 := event.GetRangeFilter(fd.Op, "balance")
-	if err2 != nil {
-		return err2
-	}
-	this.match = match
-	this.op = fd.Op
-	this.value = val
-	return nil
-}
-
-func (this *AccountBalanceFilter) Match(v interface{}) bool {
-	acc, ok := v.(*account.Account)
-	if !ok {
-		return false
-	}
-	return this.match(int64(acc.Balance), this.value)
-}
diff --git a/manager/burrow-mint/burrow-mint.go b/manager/burrow-mint/burrow-mint.go
deleted file mode 100644
index d3255452..00000000
--- a/manager/burrow-mint/burrow-mint.go
+++ /dev/null
@@ -1,216 +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 burrowmint
-
-import (
-	"bytes"
-	"fmt"
-	"sync"
-	"time"
-
-	abci "github.com/tendermint/abci/types"
-	tendermint_events "github.com/tendermint/go-events"
-	wire "github.com/tendermint/go-wire"
-
-	consensus_types "github.com/hyperledger/burrow/consensus/types"
-	"github.com/hyperledger/burrow/logging"
-	logging_types "github.com/hyperledger/burrow/logging/types"
-	sm "github.com/hyperledger/burrow/manager/burrow-mint/state"
-	manager_types "github.com/hyperledger/burrow/manager/types"
-	"github.com/hyperledger/burrow/txs"
-)
-
-//--------------------------------------------------------------------------------
-// BurrowMint holds the current state, runs transactions, computes hashes.
-// Typically two connections are opened by the tendermint core:
-// one for mempool, one for consensus.
-
-type BurrowMint struct {
-	mtx sync.Mutex
-
-	state      *sm.State
-	cache      *sm.BlockCache
-	checkCache *sm.BlockCache // for CheckTx (eg. so we get nonces right)
-
-	evc  *tendermint_events.EventCache
-	evsw tendermint_events.EventSwitch
-
-	nTxs   int // count txs in a block
-	logger logging_types.InfoTraceLogger
-}
-
-// Currently we just wrap ConsensusEngine but this interface can give us
-// arbitrary control over the type of ConsensusEngine at such a point that we
-// support others. For example it can demand a 'marker' function:
-// func IsBurrowMint_0.XX.XX_CompatibleConsensusEngine()
-type BurrowMintCompatibleConsensusEngine interface {
-	consensus_types.ConsensusEngine
-}
-
-// NOTE [ben] Compiler check to ensure BurrowMint successfully implements
-// burrow/manager/types.Application
-var _ manager_types.Application = (*BurrowMint)(nil)
-
-func (app *BurrowMint) CompatibleConsensus(consensusEngine consensus_types.ConsensusEngine) bool {
-	_, ok := consensusEngine.(BurrowMintCompatibleConsensusEngine)
-	return ok
-}
-
-func (app *BurrowMint) GetState() *sm.State {
-	app.mtx.Lock()
-	defer app.mtx.Unlock()
-	return app.state.Copy()
-}
-
-// TODO: this is used for call/callcode and to get nonces during mempool.
-// the former should work on last committed state only and the later should
-// be handled by the client, or a separate wallet-like nonce tracker thats not part of the app
-func (app *BurrowMint) GetCheckCache() *sm.BlockCache {
-	return app.checkCache
-}
-
-func NewBurrowMint(s *sm.State, evsw tendermint_events.EventSwitch,
-	logger logging_types.InfoTraceLogger) *BurrowMint {
-	return &BurrowMint{
-		state:      s,
-		cache:      sm.NewBlockCache(s),
-		checkCache: sm.NewBlockCache(s),
-		evc:        tendermint_events.NewEventCache(evsw),
-		evsw:       evsw,
-		logger:     logging.WithScope(logger, "BurrowMint"),
-	}
-}
-
-// Implements manager/types.Application
-func (app *BurrowMint) Info() (info abci.ResponseInfo) {
-	return abci.ResponseInfo{}
-}
-
-// Implements manager/types.Application
-func (app *BurrowMint) SetOption(key string, value string) (log string) {
-	return ""
-}
-
-// Implements manager/types.Application
-func (app *BurrowMint) DeliverTx(txBytes []byte) abci.Result {
-	app.nTxs += 1
-
-	// XXX: if we had tx ids we could cache the decoded txs on CheckTx
-	var n int
-	var err error
-	tx := new(txs.Tx)
-	buf := bytes.NewBuffer(txBytes)
-	wire.ReadBinaryPtr(tx, buf, len(txBytes), &n, &err)
-	if err != nil {
-		return abci.NewError(abci.CodeType_EncodingError, fmt.Sprintf("Encoding error: %v", err))
-	}
-
-	err = sm.ExecTx(app.cache, *tx, true, app.evc, app.logger)
-	if err != nil {
-		return abci.NewError(abci.CodeType_InternalError, fmt.Sprintf("Internal error: %v", err))
-	}
-
-	receipt := txs.GenerateReceipt(app.state.ChainID, *tx)
-	receiptBytes := wire.BinaryBytes(receipt)
-	return abci.NewResultOK(receiptBytes, "Success")
-}
-
-// Implements manager/types.Application
-func (app *BurrowMint) CheckTx(txBytes []byte) abci.Result {
-	var n int
-	var err error
-	tx := new(txs.Tx)
-	buf := bytes.NewBuffer(txBytes)
-	wire.ReadBinaryPtr(tx, buf, len(txBytes), &n, &err)
-	if err != nil {
-		return abci.NewError(abci.CodeType_EncodingError, fmt.Sprintf("Encoding error: %v", err))
-	}
-
-	// TODO: map ExecTx errors to sensible abci error codes
-	err = sm.ExecTx(app.checkCache, *tx, false, nil, app.logger)
-	if err != nil {
-		return abci.NewError(abci.CodeType_InternalError, fmt.Sprintf("Internal error: %v", err))
-	}
-	receipt := txs.GenerateReceipt(app.state.ChainID, *tx)
-	receiptBytes := wire.BinaryBytes(receipt)
-	return abci.NewResultOK(receiptBytes, "Success")
-}
-
-// Implements manager/types.Application
-// Commit the state (called at end of block)
-// NOTE: CheckTx/AppendTx must not run concurrently with Commit -
-//  the mempool should run during AppendTxs, but lock for Commit and Update
-func (app *BurrowMint) Commit() (res abci.Result) {
-	app.mtx.Lock() // the lock protects app.state
-	defer app.mtx.Unlock()
-
-	app.state.LastBlockHeight += 1
-	logging.InfoMsg(app.logger, "Committing block",
-		"last_block_height", app.state.LastBlockHeight)
-
-	// sync the AppendTx cache
-	app.cache.Sync()
-
-	// Refresh the checkCache with the latest commited state
-	logging.InfoMsg(app.logger, "Resetting checkCache",
-		"txs", app.nTxs)
-	app.checkCache = sm.NewBlockCache(app.state)
-
-	app.nTxs = 0
-
-	// save state to disk
-	app.state.Save()
-
-	// flush events to listeners (XXX: note issue with blocking)
-	app.evc.Flush()
-
-	// TODO: [ben] over the tendermint 0.6 TMSP interface we have
-	// no access to the block header implemented;
-	// On Tendermint v0.8 load the blockheader into the application
-	// state and remove the fixed 2-"seconds" per block internal clock.
-	// NOTE: set internal time as two seconds per block
-	app.state.LastBlockTime = app.state.LastBlockTime.Add(time.Duration(2) * time.Second)
-	appHash := app.state.Hash()
-	return abci.NewResultOK(appHash, "Success")
-}
-
-func (app *BurrowMint) Query(query abci.RequestQuery) (res abci.ResponseQuery) {
-	return abci.ResponseQuery{
-		Code: abci.CodeType_OK,
-		Log:  "success",
-	}
-}
-
-// BlockchainAware interface
-
-// Initialise the blockchain
-// validators: genesis validators from tendermint core
-func (app *BurrowMint) InitChain(validators []*abci.Validator) {
-	// Could verify agreement on initial validator set here
-}
-
-// Signals the beginning of a block
-func (app *BurrowMint) BeginBlock(hash []byte, header *abci.Header) {
-
-}
-
-// Signals the end of a blockchain, return value can be used to modify validator
-// set and voting power distribution see our BlockchainAware interface
-func (app *BurrowMint) EndBlock(height uint64) (respEndblock abci.ResponseEndBlock) {
-	// TODO: [Silas] Bondage
-	// TODO: [Silas] this might be a better place for us to dispatch new block
-	// events particularly if we want to separate ourselves from go-events
-	return
-}
diff --git a/manager/burrow-mint/evm/fake_app_state.go b/manager/burrow-mint/evm/fake_app_state.go
deleted file mode 100644
index c9b1e747..00000000
--- a/manager/burrow-mint/evm/fake_app_state.go
+++ /dev/null
@@ -1,94 +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 vm
-
-import (
-	"fmt"
-
-	"github.com/hyperledger/burrow/manager/burrow-mint/evm/sha3"
-	. "github.com/hyperledger/burrow/word256"
-)
-
-type FakeAppState struct {
-	accounts map[string]*Account
-	storage  map[string]Word256
-}
-
-func (fas *FakeAppState) GetAccount(addr Word256) *Account {
-	account := fas.accounts[addr.String()]
-	return account
-}
-
-func (fas *FakeAppState) UpdateAccount(account *Account) {
-	fas.accounts[account.Address.String()] = account
-}
-
-func (fas *FakeAppState) RemoveAccount(account *Account) {
-	_, ok := fas.accounts[account.Address.String()]
-	if !ok {
-		panic(fmt.Sprintf("Invalid account addr: %X", account.Address))
-	} else {
-		// Remove account
-		delete(fas.accounts, account.Address.String())
-	}
-}
-
-func (fas *FakeAppState) CreateAccount(creator *Account) *Account {
-	addr := createAddress(creator)
-	account := fas.accounts[addr.String()]
-	if account == nil {
-		return &Account{
-			Address: addr,
-			Balance: 0,
-			Code:    nil,
-			Nonce:   0,
-		}
-	} else {
-		panic(fmt.Sprintf("Invalid account addr: %X", addr))
-	}
-}
-
-func (fas *FakeAppState) GetStorage(addr Word256, key Word256) Word256 {
-	_, ok := fas.accounts[addr.String()]
-	if !ok {
-		panic(fmt.Sprintf("Invalid account addr: %X", addr))
-	}
-
-	value, ok := fas.storage[addr.String()+key.String()]
-	if ok {
-		return value
-	} else {
-		return Zero256
-	}
-}
-
-func (fas *FakeAppState) SetStorage(addr Word256, key Word256, value Word256) {
-	_, ok := fas.accounts[addr.String()]
-	if !ok {
-		panic(fmt.Sprintf("Invalid account addr: %X", addr))
-	}
-
-	fas.storage[addr.String()+key.String()] = value
-}
-
-// Creates a 20 byte address and bumps the nonce.
-func createAddress(creator *Account) Word256 {
-	nonce := creator.Nonce
-	creator.Nonce += 1
-	temp := make([]byte, 32+8)
-	copy(temp, creator.Address[:])
-	PutInt64BE(temp[32:], nonce)
-	return LeftPadWord256(sha3.Sha3(temp)[:20])
-}
diff --git a/manager/burrow-mint/evm/types.go b/manager/burrow-mint/evm/types.go
deleted file mode 100644
index f083812e..00000000
--- a/manager/burrow-mint/evm/types.go
+++ /dev/null
@@ -1,65 +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 vm
-
-import (
-	"fmt"
-
-	ptypes "github.com/hyperledger/burrow/permission/types"
-	. "github.com/hyperledger/burrow/word256"
-)
-
-const (
-	defaultDataStackCapacity = 10
-)
-
-type Account struct {
-	Address Word256
-	Balance int64
-	Code    []byte
-	Nonce   int64
-	Other   interface{} // For holding all other data.
-
-	Permissions ptypes.AccountPermissions
-}
-
-func (acc *Account) String() string {
-	if acc == nil {
-		return "nil-VMAccount"
-	}
-	return fmt.Sprintf("VMAccount{%X B:%v C:%X N:%v}",
-		acc.Address, acc.Balance, acc.Code, acc.Nonce)
-}
-
-type AppState interface {
-
-	// Accounts
-	GetAccount(addr Word256) *Account
-	UpdateAccount(*Account)
-	RemoveAccount(*Account)
-	CreateAccount(*Account) *Account
-
-	// Storage
-	GetStorage(Word256, Word256) Word256
-	SetStorage(Word256, Word256, Word256) // Setting to Zero is deleting.
-
-}
-
-type Params struct {
-	BlockHeight int64
-	BlockHash   Word256
-	BlockTime   int64
-	GasLimit    int64
-}
diff --git a/manager/burrow-mint/pipe.go b/manager/burrow-mint/pipe.go
deleted file mode 100644
index cb91fb2a..00000000
--- a/manager/burrow-mint/pipe.go
+++ /dev/null
@@ -1,677 +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 burrowmint
-
-import (
-	"bytes"
-	"fmt"
-
-	abci_types "github.com/tendermint/abci/types"
-	crypto "github.com/tendermint/go-crypto"
-	db "github.com/tendermint/go-db"
-	go_events "github.com/tendermint/go-events"
-	wire "github.com/tendermint/go-wire"
-	tm_types "github.com/tendermint/tendermint/types"
-
-	"github.com/hyperledger/burrow/account"
-	blockchain_types "github.com/hyperledger/burrow/blockchain/types"
-	imath "github.com/hyperledger/burrow/common/math/integral"
-	"github.com/hyperledger/burrow/config"
-	consensus_types "github.com/hyperledger/burrow/consensus/types"
-	core_types "github.com/hyperledger/burrow/core/types"
-	"github.com/hyperledger/burrow/definitions"
-	edb_event "github.com/hyperledger/burrow/event"
-	genesis "github.com/hyperledger/burrow/genesis"
-	"github.com/hyperledger/burrow/logging"
-	logging_types "github.com/hyperledger/burrow/logging/types"
-	vm "github.com/hyperledger/burrow/manager/burrow-mint/evm"
-	"github.com/hyperledger/burrow/manager/burrow-mint/state"
-	manager_types "github.com/hyperledger/burrow/manager/types"
-	rpc_tm_types "github.com/hyperledger/burrow/rpc/tendermint/core/types"
-	"github.com/hyperledger/burrow/txs"
-	"github.com/hyperledger/burrow/word256"
-)
-
-type burrowMintPipe struct {
-	burrowMintState *state.State
-	burrowMint      *BurrowMint
-	// Pipe implementations
-	accounts        *accounts
-	blockchain      blockchain_types.Blockchain
-	consensusEngine consensus_types.ConsensusEngine
-	events          edb_event.EventEmitter
-	namereg         *namereg
-	transactor      *transactor
-	// Genesis cache
-	genesisDoc   *genesis.GenesisDoc
-	genesisState *state.State
-	logger       logging_types.InfoTraceLogger
-}
-
-// Interface type assertions
-var _ definitions.Pipe = (*burrowMintPipe)(nil)
-
-var _ definitions.TendermintPipe = (*burrowMintPipe)(nil)
-
-func NewBurrowMintPipe(moduleConfig *config.ModuleConfig,
-	eventSwitch go_events.EventSwitch,
-	logger logging_types.InfoTraceLogger) (*burrowMintPipe, error) {
-
-	startedState, genesisDoc, err := startState(moduleConfig.DataDir,
-		moduleConfig.Config.GetString("db_backend"), moduleConfig.GenesisFile,
-		moduleConfig.ChainId)
-	if err != nil {
-		return nil, fmt.Errorf("Failed to start state: %v", err)
-	}
-	logger = logging.WithScope(logger, "BurrowMintPipe")
-	// assert ChainId matches genesis ChainId
-	logging.InfoMsg(logger, "Loaded state",
-		"chainId", startedState.ChainID,
-		"lastBlockHeight", startedState.LastBlockHeight,
-		"lastBlockHash", startedState.LastBlockHash)
-	// start the application
-	burrowMint := NewBurrowMint(startedState, eventSwitch, logger)
-
-	// initialise the components of the pipe
-	events := edb_event.NewEvents(eventSwitch, logger)
-	accounts := newAccounts(burrowMint)
-	namereg := newNameReg(burrowMint)
-
-	pipe := &burrowMintPipe{
-		burrowMintState: startedState,
-		burrowMint:      burrowMint,
-		accounts:        accounts,
-		events:          events,
-		namereg:         namereg,
-		// We need to set transactor later since we are introducing a mutual dependency
-		// NOTE: this will be cleaned up when the RPC is unified
-		transactor: nil,
-		// genesis cache
-		genesisDoc:   genesisDoc,
-		genesisState: nil,
-		// consensus and blockchain should both be loaded into the pipe by a higher
-		// authority - this is a sort of dependency injection pattern
-		consensusEngine: nil,
-		blockchain:      nil,
-		logger:          logger,
-	}
-
-	// NOTE: [Silas]
-	// This is something of a loopback, but seems like a nicer option than
-	// transactor calling the Tendermint native RPC (as it was before),
-	// or indeed calling this RPC over the wire given that we have direct access.
-	//
-	// We could just hand transactor a copy of Pipe, but doing it this way seems
-	// like a reasonably minimal and flexible way of providing transactor with the
-	// broadcast function it needs, without making it explicitly
-	// aware of/depend on Pipe.
-	transactor := newTransactor(moduleConfig.ChainId, eventSwitch, burrowMint,
-		events,
-		func(tx txs.Tx) error {
-			_, err := pipe.BroadcastTxSync(tx)
-			return err
-		})
-
-	pipe.transactor = transactor
-	return pipe, nil
-}
-
-//------------------------------------------------------------------------------
-// Start state
-
-// Start state tries to load the existing state in the data directory;
-// if an existing database can be loaded, it will validate that the
-// chainId in the genesis of that loaded state matches the asserted chainId.
-// If no state can be loaded, the JSON genesis file will be loaded into the
-// state database as the zero state.
-func startState(dataDir, backend, genesisFile, chainId string) (*state.State,
-	*genesis.GenesisDoc, error) {
-	// avoid Tendermints PanicSanity and return a clean error
-	if backend != db.MemDBBackendStr &&
-		backend != db.LevelDBBackendStr {
-		return nil, nil, fmt.Errorf("Database backend %s is not supported "+
-			"by burrowmint", backend)
-	}
-
-	stateDB := db.NewDB("burrowmint", backend, dataDir)
-	newState := state.LoadState(stateDB)
-	var genesisDoc *genesis.GenesisDoc
-	if newState == nil {
-		genesisDoc, newState = state.MakeGenesisStateFromFile(stateDB, genesisFile)
-		newState.Save()
-		buf, n, err := new(bytes.Buffer), new(int), new(error)
-		wire.WriteJSON(genesisDoc, buf, n, err)
-		stateDB.Set(genesis.GenDocKey, buf.Bytes())
-		if *err != nil {
-			return nil, nil, fmt.Errorf("Unable to write genesisDoc to db: %v", err)
-		}
-	} else {
-		loadedGenesisDocBytes := stateDB.Get(genesis.GenDocKey)
-		err := new(error)
-		wire.ReadJSONPtr(&genesisDoc, loadedGenesisDocBytes, err)
-		if *err != nil {
-			return nil, nil, fmt.Errorf("Unable to read genesisDoc from db on startState: %v", err)
-		}
-		// assert loaded genesis doc has the same chainId as the provided chainId
-		if genesisDoc.ChainID != chainId {
-			return nil, nil, fmt.Errorf("ChainId (%s) loaded from genesis document in existing database does not match"+
-				" configuration chainId (%s).", genesisDoc.ChainID, chainId)
-		}
-	}
-
-	return newState, genesisDoc, nil
-}
-
-//------------------------------------------------------------------------------
-// Implement definitions.Pipe for burrowMintPipe
-
-func (pipe *burrowMintPipe) Logger() logging_types.InfoTraceLogger {
-	return pipe.logger
-}
-
-func (pipe *burrowMintPipe) Accounts() definitions.Accounts {
-	return pipe.accounts
-}
-
-func (pipe *burrowMintPipe) Blockchain() blockchain_types.Blockchain {
-	return pipe.blockchain
-}
-
-func (pipe *burrowMintPipe) Events() edb_event.EventEmitter {
-	return pipe.events
-}
-
-func (pipe *burrowMintPipe) NameReg() definitions.NameReg {
-	return pipe.namereg
-}
-
-func (pipe *burrowMintPipe) Transactor() definitions.Transactor {
-	return pipe.transactor
-}
-
-func (pipe *burrowMintPipe) GetApplication() manager_types.Application {
-	return pipe.burrowMint
-}
-
-func (pipe *burrowMintPipe) SetBlockchain(
-	blockchain blockchain_types.Blockchain) error {
-	if pipe.blockchain == nil {
-		pipe.blockchain = blockchain
-	} else {
-		return fmt.Errorf("Failed to set Blockchain for pipe; already set")
-	}
-	return nil
-}
-
-func (pipe *burrowMintPipe) GetBlockchain() blockchain_types.Blockchain {
-	return pipe.blockchain
-}
-
-func (pipe *burrowMintPipe) SetConsensusEngine(
-	consensusEngine consensus_types.ConsensusEngine) error {
-	if pipe.consensusEngine == nil {
-		pipe.consensusEngine = consensusEngine
-	} else {
-		return fmt.Errorf("Failed to set consensus engine for pipe; already set")
-	}
-	return nil
-}
-
-func (pipe *burrowMintPipe) GetConsensusEngine() consensus_types.ConsensusEngine {
-	return pipe.consensusEngine
-}
-
-func (pipe *burrowMintPipe) GetTendermintPipe() (definitions.TendermintPipe,
-	error) {
-	return definitions.TendermintPipe(pipe), nil
-}
-
-func (pipe *burrowMintPipe) consensusAndManagerEvents() edb_event.EventEmitter {
-	// NOTE: [Silas] We could initialise this lazily and use the cached instance,
-	// but for the time being that feels like a premature optimisation
-	return edb_event.Multiplex(pipe.events, pipe.consensusEngine.Events())
-}
-
-//------------------------------------------------------------------------------
-// Implement definitions.TendermintPipe for burrowMintPipe
-func (pipe *burrowMintPipe) Subscribe(eventId string,
-	rpcResponseWriter func(result rpc_tm_types.BurrowResult)) (*rpc_tm_types.ResultSubscribe, error) {
-	subscriptionId, err := edb_event.GenerateSubId()
-	if err != nil {
-		return nil, err
-		logging.InfoMsg(pipe.logger, "Subscribing to event",
-			"eventId", eventId, "subscriptionId", subscriptionId)
-	}
-	pipe.consensusAndManagerEvents().Subscribe(subscriptionId, eventId,
-		func(eventData txs.EventData) {
-			result := rpc_tm_types.BurrowResult(
-				&rpc_tm_types.ResultEvent{
-					Event: eventId,
-					Data:  txs.EventData(eventData)})
-			// NOTE: EventSwitch callbacks must be nonblocking
-			rpcResponseWriter(result)
-		})
-	return &rpc_tm_types.ResultSubscribe{
-		SubscriptionId: subscriptionId,
-		Event:          eventId,
-	}, nil
-}
-
-func (pipe *burrowMintPipe) Unsubscribe(subscriptionId string) (*rpc_tm_types.ResultUnsubscribe, error) {
-	logging.InfoMsg(pipe.logger, "Unsubscribing from event",
-		"subscriptionId", subscriptionId)
-	pipe.consensusAndManagerEvents().Unsubscribe(subscriptionId)
-	return &rpc_tm_types.ResultUnsubscribe{SubscriptionId: subscriptionId}, nil
-}
-func (pipe *burrowMintPipe) GenesisState() *state.State {
-	if pipe.genesisState == nil {
-		memoryDatabase := db.NewMemDB()
-		pipe.genesisState = state.MakeGenesisState(memoryDatabase, pipe.genesisDoc)
-	}
-	return pipe.genesisState
-}
-
-func (pipe *burrowMintPipe) GenesisHash() []byte {
-	return pipe.GenesisState().Hash()
-}
-
-func (pipe *burrowMintPipe) Status() (*rpc_tm_types.ResultStatus, error) {
-	if pipe.consensusEngine == nil {
-		return nil, fmt.Errorf("Consensus Engine not initialised in burrowmint pipe.")
-	}
-	latestHeight := pipe.blockchain.Height()
-	var (
-		latestBlockMeta *tm_types.BlockMeta
-		latestBlockHash []byte
-		latestBlockTime int64
-	)
-	if latestHeight != 0 {
-		latestBlockMeta = pipe.blockchain.BlockMeta(latestHeight)
-		latestBlockHash = latestBlockMeta.Header.Hash()
-		latestBlockTime = latestBlockMeta.Header.Time.UnixNano()
-	}
-	return &rpc_tm_types.ResultStatus{
-		NodeInfo:          pipe.consensusEngine.NodeInfo(),
-		GenesisHash:       pipe.GenesisHash(),
-		PubKey:            pipe.consensusEngine.PublicValidatorKey(),
-		LatestBlockHash:   latestBlockHash,
-		LatestBlockHeight: latestHeight,
-		LatestBlockTime:   latestBlockTime}, nil
-}
-
-func (pipe *burrowMintPipe) ChainId() (*rpc_tm_types.ResultChainId, error) {
-	if pipe.blockchain == nil {
-		return nil, fmt.Errorf("Blockchain not initialised in burrowmint pipe.")
-	}
-	chainId := pipe.blockchain.ChainId()
-
-	return &rpc_tm_types.ResultChainId{
-		ChainName:   chainId, // MARMOT: copy ChainId for ChainName as a placehodlder
-		ChainId:     chainId,
-		GenesisHash: pipe.GenesisHash(),
-	}, nil
-}
-
-func (pipe *burrowMintPipe) NetInfo() (*rpc_tm_types.ResultNetInfo, error) {
-	listening := pipe.consensusEngine.IsListening()
-	listeners := []string{}
-	for _, listener := range pipe.consensusEngine.Listeners() {
-		listeners = append(listeners, listener.String())
-	}
-	peers := pipe.consensusEngine.Peers()
-	return &rpc_tm_types.ResultNetInfo{
-		Listening: listening,
-		Listeners: listeners,
-		Peers:     peers,
-	}, nil
-}
-
-func (pipe *burrowMintPipe) Genesis() (*rpc_tm_types.ResultGenesis, error) {
-	return &rpc_tm_types.ResultGenesis{
-		// TODO: [ben] sharing pointer to unmutated GenesisDoc, but is not immutable
-		Genesis: pipe.genesisDoc,
-	}, nil
-}
-
-// Accounts
-func (pipe *burrowMintPipe) GetAccount(address []byte) (*rpc_tm_types.ResultGetAccount,
-	error) {
-	cache := pipe.burrowMint.GetCheckCache()
-	account := cache.GetAccount(address)
-	return &rpc_tm_types.ResultGetAccount{Account: account}, nil
-}
-
-func (pipe *burrowMintPipe) ListAccounts() (*rpc_tm_types.ResultListAccounts, error) {
-	var blockHeight int
-	var accounts []*account.Account
-	state := pipe.burrowMint.GetState()
-	blockHeight = state.LastBlockHeight
-	state.GetAccounts().Iterate(func(key []byte, value []byte) bool {
-		accounts = append(accounts, account.DecodeAccount(value))
-		return false
-	})
-	return &rpc_tm_types.ResultListAccounts{blockHeight, accounts}, nil
-}
-
-func (pipe *burrowMintPipe) GetStorage(address, key []byte) (*rpc_tm_types.ResultGetStorage,
-	error) {
-	state := pipe.burrowMint.GetState()
-	// state := consensusState.GetState()
-	account := state.GetAccount(address)
-	if account == nil {
-		return nil, fmt.Errorf("UnknownAddress: %X", address)
-	}
-	storageRoot := account.StorageRoot
-	storageTree := state.LoadStorage(storageRoot)
-
-	_, value, exists := storageTree.Get(
-		word256.LeftPadWord256(key).Bytes())
-	if !exists {
-		// value == nil {
-		return &rpc_tm_types.ResultGetStorage{key, nil}, nil
-	}
-	return &rpc_tm_types.ResultGetStorage{key, value}, nil
-}
-
-func (pipe *burrowMintPipe) DumpStorage(address []byte) (*rpc_tm_types.ResultDumpStorage,
-	error) {
-	state := pipe.burrowMint.GetState()
-	account := state.GetAccount(address)
-	if account == nil {
-		return nil, fmt.Errorf("UnknownAddress: %X", address)
-	}
-	storageRoot := account.StorageRoot
-	storageTree := state.LoadStorage(storageRoot)
-	storageItems := []rpc_tm_types.StorageItem{}
-	storageTree.Iterate(func(key []byte, value []byte) bool {
-		storageItems = append(storageItems, rpc_tm_types.StorageItem{key,
-			value})
-		return false
-	})
-	return &rpc_tm_types.ResultDumpStorage{storageRoot, storageItems}, nil
-}
-
-// Call
-// NOTE: this function is used from 46657 and has sibling on 1337
-// in transactor.go
-// TODO: [ben] resolve incompatibilities in byte representation for 0.12.0 release
-func (pipe *burrowMintPipe) Call(fromAddress, toAddress, data []byte) (*rpc_tm_types.ResultCall,
-	error) {
-	if vm.RegisteredNativeContract(word256.LeftPadWord256(toAddress)) {
-		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)
-	}
-	st := pipe.burrowMint.GetState()
-	cache := state.NewBlockCache(st)
-	outAcc := cache.GetAccount(toAddress)
-	if outAcc == nil {
-		return nil, fmt.Errorf("Account %x does not exist", toAddress)
-	}
-	if fromAddress == nil {
-		fromAddress = []byte{}
-	}
-	callee := toVMAccount(outAcc)
-	caller := &vm.Account{Address: word256.LeftPadWord256(fromAddress)}
-	txCache := state.NewTxCache(cache)
-	gasLimit := st.GetGasLimit()
-	params := vm.Params{
-		BlockHeight: int64(st.LastBlockHeight),
-		BlockHash:   word256.LeftPadWord256(st.LastBlockHash),
-		BlockTime:   st.LastBlockTime.Unix(),
-		GasLimit:    gasLimit,
-	}
-
-	vmach := vm.NewVM(txCache, vm.DefaultDynamicMemoryProvider, params,
-		caller.Address, nil)
-	gas := gasLimit
-	ret, err := vmach.Call(caller, callee, callee.Code, data, 0, &gas)
-	if err != nil {
-		return nil, err
-	}
-	gasUsed := gasLimit - gas
-	// here return bytes are not hex encoded; on the sibling function
-	// they are
-	return &rpc_tm_types.ResultCall{Return: ret, GasUsed: gasUsed}, nil
-}
-
-func (pipe *burrowMintPipe) CallCode(fromAddress, code, data []byte) (*rpc_tm_types.ResultCall,
-	error) {
-	st := pipe.burrowMint.GetState()
-	cache := pipe.burrowMint.GetCheckCache()
-	callee := &vm.Account{Address: word256.LeftPadWord256(fromAddress)}
-	caller := &vm.Account{Address: word256.LeftPadWord256(fromAddress)}
-	txCache := state.NewTxCache(cache)
-	gasLimit := st.GetGasLimit()
-	params := vm.Params{
-		BlockHeight: int64(st.LastBlockHeight),
-		BlockHash:   word256.LeftPadWord256(st.LastBlockHash),
-		BlockTime:   st.LastBlockTime.Unix(),
-		GasLimit:    gasLimit,
-	}
-
-	vmach := vm.NewVM(txCache, vm.DefaultDynamicMemoryProvider, params,
-		caller.Address, nil)
-	gas := gasLimit
-	ret, err := vmach.Call(caller, callee, code, data, 0, &gas)
-	if err != nil {
-		return nil, err
-	}
-	gasUsed := gasLimit - gas
-	return &rpc_tm_types.ResultCall{Return: ret, GasUsed: gasUsed}, nil
-}
-
-// TODO: [ben] deprecate as we should not allow unsafe behaviour
-// where a user is allowed to send a private key over the wire,
-// especially unencrypted.
-func (pipe *burrowMintPipe) SignTransaction(tx txs.Tx,
-	privAccounts []*account.PrivAccount) (*rpc_tm_types.ResultSignTx,
-	error) {
-
-	for i, privAccount := range privAccounts {
-		if privAccount == nil || privAccount.PrivKey == nil {
-			return nil, fmt.Errorf("Invalid (empty) privAccount @%v", i)
-		}
-	}
-	switch tx.(type) {
-	case *txs.SendTx:
-		sendTx := tx.(*txs.SendTx)
-		for i, input := range sendTx.Inputs {
-			input.PubKey = privAccounts[i].PubKey
-			input.Signature = privAccounts[i].Sign(pipe.transactor.chainID, sendTx)
-		}
-	case *txs.CallTx:
-		callTx := tx.(*txs.CallTx)
-		callTx.Input.PubKey = privAccounts[0].PubKey
-		callTx.Input.Signature = privAccounts[0].Sign(pipe.transactor.chainID, callTx)
-	case *txs.BondTx:
-		bondTx := tx.(*txs.BondTx)
-		// the first privaccount corresponds to the BondTx pub key.
-		// the rest to the inputs
-		bondTx.Signature = privAccounts[0].Sign(pipe.transactor.chainID, bondTx).(crypto.SignatureEd25519)
-		for i, input := range bondTx.Inputs {
-			input.PubKey = privAccounts[i+1].PubKey
-			input.Signature = privAccounts[i+1].Sign(pipe.transactor.chainID, bondTx)
-		}
-	case *txs.UnbondTx:
-		unbondTx := tx.(*txs.UnbondTx)
-		unbondTx.Signature = privAccounts[0].Sign(pipe.transactor.chainID, unbondTx).(crypto.SignatureEd25519)
-	case *txs.RebondTx:
-		rebondTx := tx.(*txs.RebondTx)
-		rebondTx.Signature = privAccounts[0].Sign(pipe.transactor.chainID, rebondTx).(crypto.SignatureEd25519)
-	}
-	return &rpc_tm_types.ResultSignTx{tx}, nil
-}
-
-// Name registry
-func (pipe *burrowMintPipe) GetName(name string) (*rpc_tm_types.ResultGetName, error) {
-	currentState := pipe.burrowMint.GetState()
-	entry := currentState.GetNameRegEntry(name)
-	if entry == nil {
-		return nil, fmt.Errorf("Name %s not found", name)
-	}
-	return &rpc_tm_types.ResultGetName{entry}, nil
-}
-
-func (pipe *burrowMintPipe) ListNames() (*rpc_tm_types.ResultListNames, error) {
-	var blockHeight int
-	var names []*core_types.NameRegEntry
-	currentState := pipe.burrowMint.GetState()
-	blockHeight = currentState.LastBlockHeight
-	currentState.GetNames().Iterate(func(key []byte, value []byte) bool {
-		names = append(names, state.DecodeNameRegEntry(value))
-		return false
-	})
-	return &rpc_tm_types.ResultListNames{blockHeight, names}, nil
-}
-
-func (pipe *burrowMintPipe) broadcastTx(tx txs.Tx,
-	callback func(res *abci_types.Response)) (*rpc_tm_types.ResultBroadcastTx, error) {
-
-	txBytes, err := txs.EncodeTx(tx)
-	if err != nil {
-		return nil, fmt.Errorf("Error encoding transaction: %v", err)
-	}
-	err = pipe.consensusEngine.BroadcastTransaction(txBytes, callback)
-	if err != nil {
-		return nil, fmt.Errorf("Error broadcasting transaction: %v", err)
-	}
-	return &rpc_tm_types.ResultBroadcastTx{}, nil
-}
-
-// Memory pool
-// NOTE: txs must be signed
-func (pipe *burrowMintPipe) BroadcastTxAsync(tx txs.Tx) (*rpc_tm_types.ResultBroadcastTx, error) {
-	return pipe.broadcastTx(tx, nil)
-}
-
-func (pipe *burrowMintPipe) BroadcastTxSync(tx txs.Tx) (*rpc_tm_types.ResultBroadcastTx, error) {
-	responseChannel := make(chan *abci_types.Response, 1)
-	_, err := pipe.broadcastTx(tx,
-		func(res *abci_types.Response) {
-			responseChannel <- res
-		})
-	if err != nil {
-		return nil, err
-	}
-	// NOTE: [ben] This Response is set in /consensus/tendermint/local_client.go
-	// a call to Application, here implemented by BurrowMint, over local callback,
-	// or abci RPC call.  Hence the result is determined by BurrowMint/burrowmint.go
-	// CheckTx() Result (Result converted to ReqRes into Response returned here)
-	// NOTE: [ben] BroadcastTx just calls CheckTx in Tendermint (oddly... [Silas])
-	response := <-responseChannel
-	responseCheckTx := response.GetCheckTx()
-	if responseCheckTx == nil {
-		return nil, fmt.Errorf("Error, application did not return CheckTx response.")
-	}
-	resultBroadCastTx := &rpc_tm_types.ResultBroadcastTx{
-		Code: responseCheckTx.Code,
-		Data: responseCheckTx.Data,
-		Log:  responseCheckTx.Log,
-	}
-	switch responseCheckTx.Code {
-	case abci_types.CodeType_OK:
-		return resultBroadCastTx, nil
-	case abci_types.CodeType_EncodingError:
-		return resultBroadCastTx, fmt.Errorf(resultBroadCastTx.Log)
-	case abci_types.CodeType_InternalError:
-		return resultBroadCastTx, fmt.Errorf(resultBroadCastTx.Log)
-	default:
-		logging.InfoMsg(pipe.logger, "Unknown error returned from Tendermint CheckTx on BroadcastTxSync",
-			"application", "burrowmint",
-			"abci_code_type", responseCheckTx.Code,
-			"abci_log", responseCheckTx.Log,
-		)
-		return resultBroadCastTx, fmt.Errorf("Unknown error returned: " + responseCheckTx.Log)
-	}
-}
-
-func (pipe *burrowMintPipe) ListUnconfirmedTxs(maxTxs int) (*rpc_tm_types.ResultListUnconfirmedTxs, error) {
-	// Get all transactions for now
-	transactions, err := pipe.consensusEngine.ListUnconfirmedTxs(maxTxs)
-	if err != nil {
-		return nil, err
-	}
-	return &rpc_tm_types.ResultListUnconfirmedTxs{
-		N:   len(transactions),
-		Txs: transactions,
-	}, nil
-}
-
-// Returns the current blockchain height and metadata for a range of blocks
-// between minHeight and maxHeight. Only returns maxBlockLookback block metadata
-// 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 (pipe *burrowMintPipe) BlockchainInfo(minHeight, maxHeight,
-	maxBlockLookback int) (*rpc_tm_types.ResultBlockchainInfo, error) {
-
-	latestHeight := pipe.blockchain.Height()
-
-	if maxHeight < 1 {
-		maxHeight = latestHeight
-	} else {
-		maxHeight = imath.MinInt(latestHeight, maxHeight)
-	}
-	if minHeight < 1 {
-		minHeight = imath.MaxInt(1, maxHeight-maxBlockLookback)
-	}
-
-	blockMetas := []*tm_types.BlockMeta{}
-	for height := maxHeight; height >= minHeight; height-- {
-		blockMeta := pipe.blockchain.BlockMeta(height)
-		blockMetas = append(blockMetas, blockMeta)
-	}
-
-	return &rpc_tm_types.ResultBlockchainInfo{
-		LastHeight: latestHeight,
-		BlockMetas: blockMetas,
-	}, nil
-}
-
-func (pipe *burrowMintPipe) GetBlock(height int) (*rpc_tm_types.ResultGetBlock, error) {
-	return &rpc_tm_types.ResultGetBlock{
-		Block:     pipe.blockchain.Block(height),
-		BlockMeta: pipe.blockchain.BlockMeta(height),
-	}, nil
-}
-
-func (pipe *burrowMintPipe) ListValidators() (*rpc_tm_types.ResultListValidators, error) {
-	validators := pipe.consensusEngine.ListValidators()
-	consensusState := pipe.consensusEngine.ConsensusState()
-	// TODO: when we reintroduce support for bonding and unbonding update this
-	// to reflect the mutable bonding state
-	return &rpc_tm_types.ResultListValidators{
-		BlockHeight:         consensusState.Height,
-		BondedValidators:    validators,
-		UnbondingValidators: nil,
-	}, nil
-}
-
-func (pipe *burrowMintPipe) DumpConsensusState() (*rpc_tm_types.ResultDumpConsensusState, error) {
-	statesMap := pipe.consensusEngine.PeerConsensusStates()
-	peerStates := make([]*rpc_tm_types.ResultPeerConsensusState, len(statesMap))
-	for key, peerState := range statesMap {
-		peerStates = append(peerStates, &rpc_tm_types.ResultPeerConsensusState{
-			PeerKey:            key,
-			PeerConsensusState: peerState,
-		})
-	}
-	dump := rpc_tm_types.ResultDumpConsensusState{
-		ConsensusState:      pipe.consensusEngine.ConsensusState(),
-		PeerConsensusStates: peerStates,
-	}
-	return &dump, nil
-}
diff --git a/manager/burrow-mint/state/block_cache.go b/manager/burrow-mint/state/block_cache.go
deleted file mode 100644
index 3ba8a456..00000000
--- a/manager/burrow-mint/state/block_cache.go
+++ /dev/null
@@ -1,304 +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 state
-
-import (
-	"bytes"
-	"fmt"
-	"sort"
-
-	acm "github.com/hyperledger/burrow/account"
-	"github.com/hyperledger/burrow/common/sanity"
-	core_types "github.com/hyperledger/burrow/core/types"
-	. "github.com/hyperledger/burrow/word256"
-
-	dbm "github.com/tendermint/go-db"
-	"github.com/tendermint/go-merkle"
-)
-
-func makeStorage(db dbm.DB, root []byte) merkle.Tree {
-	storage := merkle.NewIAVLTree(1024, db)
-	storage.Load(root)
-	return storage
-}
-
-// The blockcache helps prevent unnecessary IAVLTree updates and garbage generation.
-type BlockCache struct {
-	db       dbm.DB
-	backend  *State
-	accounts map[string]accountInfo
-	storages map[Tuple256]storageInfo
-	names    map[string]nameInfo
-}
-
-func NewBlockCache(backend *State) *BlockCache {
-	return &BlockCache{
-		db:       backend.DB,
-		backend:  backend,
-		accounts: make(map[string]accountInfo),
-		storages: make(map[Tuple256]storageInfo),
-		names:    make(map[string]nameInfo),
-	}
-}
-
-func (cache *BlockCache) State() *State {
-	return cache.backend
-}
-
-//-------------------------------------
-// BlockCache.account
-
-func (cache *BlockCache) GetAccount(addr []byte) *acm.Account {
-	acc, _, removed, _ := cache.accounts[string(addr)].unpack()
-	if removed {
-		return nil
-	} else if acc != nil {
-		return acc
-	} else {
-		acc = cache.backend.GetAccount(addr)
-		cache.accounts[string(addr)] = accountInfo{acc, nil, false, false}
-		return acc
-	}
-}
-
-func (cache *BlockCache) UpdateAccount(acc *acm.Account) {
-	addr := acc.Address
-	_, storage, removed, _ := cache.accounts[string(addr)].unpack()
-	if removed {
-		sanity.PanicSanity("UpdateAccount on a removed account")
-	}
-	cache.accounts[string(addr)] = accountInfo{acc, storage, false, true}
-}
-
-func (cache *BlockCache) RemoveAccount(addr []byte) {
-	_, _, removed, _ := cache.accounts[string(addr)].unpack()
-	if removed {
-		sanity.PanicSanity("RemoveAccount on a removed account")
-	}
-	cache.accounts[string(addr)] = accountInfo{nil, nil, true, false}
-}
-
-// BlockCache.account
-//-------------------------------------
-// BlockCache.storage
-
-func (cache *BlockCache) GetStorage(addr Word256, key Word256) (value Word256) {
-	// Check cache
-	info, ok := cache.storages[Tuple256{addr, key}]
-	if ok {
-		return info.value
-	}
-
-	// Get or load storage
-	acc, storage, removed, dirty := cache.accounts[string(addr.Postfix(20))].unpack()
-	if removed {
-		sanity.PanicSanity("GetStorage() on removed account")
-	}
-	if acc != nil && storage == nil {
-		storage = makeStorage(cache.db, acc.StorageRoot)
-		cache.accounts[string(addr.Postfix(20))] = accountInfo{acc, storage, false, dirty}
-	} else if acc == nil {
-		return Zero256
-	}
-
-	// Load and set cache
-	_, val_, _ := storage.Get(key.Bytes())
-	value = Zero256
-	if val_ != nil {
-		value = LeftPadWord256(val_)
-	}
-	cache.storages[Tuple256{addr, key}] = storageInfo{value, false}
-	return value
-}
-
-// NOTE: Set value to zero to removed from the trie.
-func (cache *BlockCache) SetStorage(addr Word256, key Word256, value Word256) {
-	_, _, removed, _ := cache.accounts[string(addr.Postfix(20))].unpack()
-	if removed {
-		sanity.PanicSanity("SetStorage() on a removed account")
-	}
-	cache.storages[Tuple256{addr, key}] = storageInfo{value, true}
-}
-
-// BlockCache.storage
-//-------------------------------------
-// BlockCache.names
-
-func (cache *BlockCache) GetNameRegEntry(name string) *core_types.NameRegEntry {
-	entry, removed, _ := cache.names[name].unpack()
-	if removed {
-		return nil
-	} else if entry != nil {
-		return entry
-	} else {
-		entry = cache.backend.GetNameRegEntry(name)
-		cache.names[name] = nameInfo{entry, false, false}
-		return entry
-	}
-}
-
-func (cache *BlockCache) UpdateNameRegEntry(entry *core_types.NameRegEntry) {
-	name := entry.Name
-	cache.names[name] = nameInfo{entry, false, true}
-}
-
-func (cache *BlockCache) RemoveNameRegEntry(name string) {
-	_, removed, _ := cache.names[name].unpack()
-	if removed {
-		sanity.PanicSanity("RemoveNameRegEntry on a removed entry")
-	}
-	cache.names[name] = nameInfo{nil, true, false}
-}
-
-// BlockCache.names
-//-------------------------------------
-
-// CONTRACT the updates are in deterministic order.
-func (cache *BlockCache) Sync() {
-
-	// Determine order for storage updates
-	// The address comes first so it'll be grouped.
-	storageKeys := make([]Tuple256, 0, len(cache.storages))
-	for keyTuple := range cache.storages {
-		storageKeys = append(storageKeys, keyTuple)
-	}
-	Tuple256Slice(storageKeys).Sort()
-
-	// Update storage for all account/key.
-	// Later we'll iterate over all the users and save storage + update storage root.
-	var (
-		curAddr       Word256
-		curAcc        *acm.Account
-		curAccRemoved bool
-		curStorage    merkle.Tree
-	)
-	for _, storageKey := range storageKeys {
-		addr, key := Tuple256Split(storageKey)
-		if addr != curAddr || curAcc == nil {
-			acc, storage, removed, _ := cache.accounts[string(addr.Postfix(20))].unpack()
-			if !removed && storage == nil {
-				storage = makeStorage(cache.db, acc.StorageRoot)
-			}
-			curAddr = addr
-			curAcc = acc
-			curAccRemoved = removed
-			curStorage = storage
-		}
-		if curAccRemoved {
-			continue
-		}
-		value, dirty := cache.storages[storageKey].unpack()
-		if !dirty {
-			continue
-		}
-		if value.IsZero() {
-			curStorage.Remove(key.Bytes())
-		} else {
-			curStorage.Set(key.Bytes(), value.Bytes())
-			cache.accounts[string(addr.Postfix(20))] = accountInfo{curAcc, curStorage, false, true}
-		}
-	}
-
-	// Determine order for accounts
-	addrStrs := []string{}
-	for addrStr := range cache.accounts {
-		addrStrs = append(addrStrs, addrStr)
-	}
-	sort.Strings(addrStrs)
-
-	// Update or delete accounts.
-	for _, addrStr := range addrStrs {
-		acc, storage, removed, dirty := cache.accounts[addrStr].unpack()
-		if removed {
-			removed := cache.backend.RemoveAccount([]byte(addrStr))
-			if !removed {
-				sanity.PanicCrisis(fmt.Sprintf("Could not remove account to be removed: %X", acc.Address))
-			}
-		} else {
-			if acc == nil {
-				continue
-			}
-			if storage != nil {
-				newStorageRoot := storage.Save()
-				if !bytes.Equal(newStorageRoot, acc.StorageRoot) {
-					acc.StorageRoot = newStorageRoot
-					dirty = true
-				}
-			}
-			if dirty {
-				cache.backend.UpdateAccount(acc)
-			}
-		}
-	}
-
-	// Determine order for names
-	// note names may be of any length less than some limit
-	nameStrs := []string{}
-	for nameStr := range cache.names {
-		nameStrs = append(nameStrs, nameStr)
-	}
-	sort.Strings(nameStrs)
-
-	// Update or delete names.
-	for _, nameStr := range nameStrs {
-		entry, removed, dirty := cache.names[nameStr].unpack()
-		if removed {
-			removed := cache.backend.RemoveNameRegEntry(nameStr)
-			if !removed {
-				sanity.PanicCrisis(fmt.Sprintf("Could not remove namereg entry to be removed: %s", nameStr))
-			}
-		} else {
-			if entry == nil {
-				continue
-			}
-			if dirty {
-				cache.backend.UpdateNameRegEntry(entry)
-			}
-		}
-	}
-
-}
-
-//-----------------------------------------------------------------------------
-
-type accountInfo struct {
-	account *acm.Account
-	storage merkle.Tree
-	removed bool
-	dirty   bool
-}
-
-func (accInfo accountInfo) unpack() (*acm.Account, merkle.Tree, bool, bool) {
-	return accInfo.account, accInfo.storage, accInfo.removed, accInfo.dirty
-}
-
-type storageInfo struct {
-	value Word256
-	dirty bool
-}
-
-func (stjInfo storageInfo) unpack() (Word256, bool) {
-	return stjInfo.value, stjInfo.dirty
-}
-
-type nameInfo struct {
-	name    *core_types.NameRegEntry
-	removed bool
-	dirty   bool
-}
-
-func (nInfo nameInfo) unpack() (*core_types.NameRegEntry, bool, bool) {
-	return nInfo.name, nInfo.removed, nInfo.dirty
-}
diff --git a/manager/burrow-mint/state/common.go b/manager/burrow-mint/state/common.go
deleted file mode 100644
index 37cf6ca1..00000000
--- a/manager/burrow-mint/state/common.go
+++ /dev/null
@@ -1,32 +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 state
-
-import (
-	acm "github.com/hyperledger/burrow/account"
-	"github.com/hyperledger/burrow/manager/burrow-mint/evm"
-	. "github.com/hyperledger/burrow/word256"
-)
-
-type AccountGetter interface {
-	GetAccount(addr []byte) *acm.Account
-}
-
-type VMAccountState interface {
-	GetAccount(addr Word256) *vm.Account
-	UpdateAccount(acc *vm.Account)
-	RemoveAccount(acc *vm.Account)
-	CreateAccount(creator *vm.Account) *vm.Account
-}
diff --git a/manager/burrow-mint/state/genesis_test.go b/manager/burrow-mint/state/genesis_test.go
deleted file mode 100644
index 983b5cb5..00000000
--- a/manager/burrow-mint/state/genesis_test.go
+++ /dev/null
@@ -1,172 +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 state
-
-import (
-	"bytes"
-	"encoding/hex"
-	"fmt"
-	"sort"
-	"testing"
-	"time"
-
-	acm "github.com/hyperledger/burrow/account"
-	"github.com/hyperledger/burrow/common/random"
-	genesis "github.com/hyperledger/burrow/genesis"
-	ptypes "github.com/hyperledger/burrow/permission/types"
-
-	tdb "github.com/tendermint/go-db"
-	"github.com/tendermint/tendermint/types"
-)
-
-var chain_id = "lone_ranger"
-var addr1, _ = hex.DecodeString("964B1493BBE3312278B7DEB94C39149F7899A345")
-var send1 = 1
-var perms, setbit = 66, 70
-var accName = "me"
-var roles1 = []string{"master", "universal-ruler"}
-var amt1 int64 = 1000000
-var g1 = fmt.Sprintf(`
-{
-    "chain_id":"%s",
-    "accounts": [
-        {
-            "address": "%X",
-            "amount": %d,
-	    	"name": "%s",
-            "permissions": {
-		    "base": {
-			    "perms": %d,
-			    "set": %d
-		    },
-            	    "roles": [
-			"%s",
-			"%s"
-            	]
-	    }
-        }
-    ],
-    "validators": [
-        {
-            "amount": 100000000,
-            "pub_key": [1,"F6C79CF0CB9D66B677988BCB9B8EADD9A091CD465A60542A8AB85476256DBA92"],
-            "unbond_to": [
-                {
-                    "address": "964B1493BBE3312278B7DEB94C39149F7899A345",
-                    "amount": 10000000
-                }
-            ]
-        }
-    ]
-}
-`, chain_id, addr1, amt1, accName, perms, setbit, roles1[0], roles1[1])
-
-func TestGenesisReadable(t *testing.T) {
-	genDoc := genesis.GenesisDocFromJSON([]byte(g1))
-	if genDoc.ChainID != chain_id {
-		t.Fatalf("Incorrect chain id. Got %d, expected %d\n", genDoc.ChainID, chain_id)
-	}
-	acc := genDoc.Accounts[0]
-	if !bytes.Equal(acc.Address, addr1) {
-		t.Fatalf("Incorrect address for account. Got %X, expected %X\n", acc.Address, addr1)
-	}
-	if acc.Amount != amt1 {
-		t.Fatalf("Incorrect amount for account. Got %d, expected %d\n", acc.Amount, amt1)
-	}
-	if acc.Name != accName {
-		t.Fatalf("Incorrect name for account. Got %s, expected %s\n", acc.Name, accName)
-	}
-
-	perm, _ := acc.Permissions.Base.Get(ptypes.Send)
-	if perm != (send1 > 0) {
-		t.Fatalf("Incorrect permission for send. Got %v, expected %v\n", perm, send1 > 0)
-	}
-}
-
-func TestGenesisMakeState(t *testing.T) {
-	genDoc := genesis.GenesisDocFromJSON([]byte(g1))
-	db := tdb.NewMemDB()
-	st := MakeGenesisState(db, genDoc)
-	acc := st.GetAccount(addr1)
-	v, _ := acc.Permissions.Base.Get(ptypes.Send)
-	if v != (send1 > 0) {
-		t.Fatalf("Incorrect permission for send. Got %v, expected %v\n", v, send1 > 0)
-	}
-}
-
-//-------------------------------------------------------
-
-func RandGenesisState(numAccounts int, randBalance bool, minBalance int64, numValidators int, randBonded bool, minBonded int64) (*State, []*acm.PrivAccount, []*types.PrivValidator) {
-	db := tdb.NewMemDB()
-	genDoc, privAccounts, privValidators := RandGenesisDoc(numAccounts, randBalance, minBalance, numValidators, randBonded, minBonded)
-	s0 := MakeGenesisState(db, genDoc)
-	s0.Save()
-	return s0, privAccounts, privValidators
-}
-
-func RandAccount(randBalance bool, minBalance int64) (*acm.Account, *acm.PrivAccount) {
-	privAccount := acm.GenPrivAccount()
-	perms := ptypes.DefaultAccountPermissions
-	acc := &acm.Account{
-		Address:     privAccount.PubKey.Address(),
-		PubKey:      privAccount.PubKey,
-		Sequence:    random.RandInt(),
-		Balance:     minBalance,
-		Permissions: perms,
-	}
-	if randBalance {
-		acc.Balance += int64(random.RandUint32())
-	}
-	return acc, privAccount
-}
-
-func RandGenesisDoc(numAccounts int, randBalance bool, minBalance int64, numValidators int, randBonded bool, minBonded int64) (*genesis.GenesisDoc, []*acm.PrivAccount, []*types.PrivValidator) {
-	accounts := make([]genesis.GenesisAccount, numAccounts)
-	privAccounts := make([]*acm.PrivAccount, numAccounts)
-	defaultPerms := ptypes.DefaultAccountPermissions
-	for i := 0; i < numAccounts; i++ {
-		account, privAccount := RandAccount(randBalance, minBalance)
-		accounts[i] = genesis.GenesisAccount{
-			Address:     account.Address,
-			Amount:      account.Balance,
-			Permissions: &defaultPerms, // This will get copied into each state.Account.
-		}
-		privAccounts[i] = privAccount
-	}
-	validators := make([]genesis.GenesisValidator, numValidators)
-	privValidators := make([]*types.PrivValidator, numValidators)
-	for i := 0; i < numValidators; i++ {
-		valInfo, privVal := types.RandValidator(randBonded, minBonded)
-		validators[i] = genesis.GenesisValidator{
-			PubKey: valInfo.PubKey,
-			Amount: valInfo.VotingPower,
-			UnbondTo: []genesis.BasicAccount{
-				{
-					Address: valInfo.PubKey.Address(),
-					Amount:  valInfo.VotingPower,
-				},
-			},
-		}
-		privValidators[i] = privVal
-	}
-	sort.Sort(types.PrivValidatorsByAddress(privValidators))
-	return &genesis.GenesisDoc{
-		GenesisTime: time.Now(),
-		ChainID:     "tendermint_test",
-		Accounts:    accounts,
-		Validators:  validators,
-	}, privAccounts, privValidators
-
-}
diff --git a/manager/burrow-mint/state/permissions_test.go b/manager/burrow-mint/state/permissions_test.go
deleted file mode 100644
index 4f550efd..00000000
--- a/manager/burrow-mint/state/permissions_test.go
+++ /dev/null
@@ -1,1314 +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 state
-
-import (
-	"bytes"
-	"fmt"
-	"strconv"
-	"testing"
-	"time"
-
-	acm "github.com/hyperledger/burrow/account"
-	genesis "github.com/hyperledger/burrow/genesis"
-	"github.com/hyperledger/burrow/manager/burrow-mint/evm"
-	. "github.com/hyperledger/burrow/manager/burrow-mint/evm/opcodes"
-	ptypes "github.com/hyperledger/burrow/permission/types"
-	"github.com/hyperledger/burrow/txs"
-	. "github.com/hyperledger/burrow/word256"
-
-	"github.com/hyperledger/burrow/logging/lifecycle"
-	"github.com/tendermint/go-crypto"
-	dbm "github.com/tendermint/go-db"
-	"github.com/tendermint/go-events"
-	"github.com/tendermint/tendermint/config/tendermint_test"
-)
-
-func init() {
-	tendermint_test.ResetConfig("permissions_test")
-}
-
-var (
-	dbBackend           = "memdb"
-	dbDir               = ""
-	permissionsContract = vm.SNativeContracts()["Permissions"]
-)
-
-/*
-Permission Tests:
-
-- SendTx:
-x	- 1 input, no perm, call perm, create perm
-x	- 1 input, perm
-x	- 2 inputs, one with perm one without
-
-- CallTx, CALL
-x	- 1 input, no perm, send perm, create perm
-x	- 1 input, perm
-x	- contract runs call but doesn't have call perm
-x	- contract runs call and has call perm
-x	- contract runs call (with perm), runs contract that runs call (without perm)
-x	- contract runs call (with perm), runs contract that runs call (with perm)
-
-- CallTx for Create, CREATE
-x	- 1 input, no perm, send perm, call perm
-x 	- 1 input, perm
-x	- contract runs create but doesn't have create perm
-x	- contract runs create but has perm
-x	- contract runs call with empty address (has call and create perm)
-
-- NameTx
-	- no perm, send perm, call perm
-	- with perm
-
-- BondTx
-x	- 1 input, no perm
-x	- 1 input, perm
-x	- 1 bonder with perm, input without send or bond
-x	- 1 bonder with perm, input with send
-x	- 1 bonder with perm, input with bond
-x	- 2 inputs, one with perm one without
-
-- SendTx for new account
-x 	- 1 input, 1 unknown ouput, input with send, not create  (fail)
-x 	- 1 input, 1 unknown ouput, input with send and create (pass)
-x 	- 2 inputs, 1 unknown ouput, both inputs with send, one with create, one without (fail)
-x 	- 2 inputs, 1 known output, 1 unknown ouput, one input with create, one without (fail)
-x 	- 2 inputs, 1 unknown ouput, both inputs with send, both inputs with create (pass )
-x 	- 2 inputs, 1 known output, 1 unknown ouput, both inputs with create, (pass)
-
-
-- CALL for new account
-x	- unknown output, without create (fail)
-x	- unknown output, with create (pass)
-
-
-- SNative (CallTx, CALL):
-	- for each of CallTx, Call
-x		- call each snative without permission, fails
-x		- call each snative with permission, pass
-	- list:
-x		- base: has,set,unset
-x		- globals: set
-x 		- roles: has, add, rm
-
-
-*/
-
-// keys
-var user = makeUsers(10)
-var chainID = "testchain"
-var logger, _ = lifecycle.NewStdErrLogger()
-
-func makeUsers(n int) []*acm.PrivAccount {
-	accounts := []*acm.PrivAccount{}
-	for i := 0; i < n; i++ {
-		secret := ("mysecret" + strconv.Itoa(i))
-		user := acm.GenPrivAccountFromSecret(secret)
-		accounts = append(accounts, user)
-	}
-	return accounts
-}
-
-var (
-	PermsAllFalse = ptypes.ZeroAccountPermissions
-)
-
-func newBaseGenDoc(globalPerm, accountPerm ptypes.AccountPermissions) genesis.GenesisDoc {
-	genAccounts := []genesis.GenesisAccount{}
-	for _, u := range user[:5] {
-		accountPermCopy := accountPerm // Create new instance for custom overridability.
-		genAccounts = append(genAccounts, genesis.GenesisAccount{
-			Address:     u.Address,
-			Amount:      1000000,
-			Permissions: &accountPermCopy,
-		})
-	}
-
-	return genesis.GenesisDoc{
-		GenesisTime: time.Now(),
-		ChainID:     chainID,
-		Params: &genesis.GenesisParams{
-			GlobalPermissions: &globalPerm,
-		},
-		Accounts: genAccounts,
-		Validators: []genesis.GenesisValidator{
-			genesis.GenesisValidator{
-				PubKey: user[0].PubKey.(crypto.PubKeyEd25519),
-				Amount: 10,
-				UnbondTo: []genesis.BasicAccount{
-					genesis.BasicAccount{
-						Address: user[0].Address,
-					},
-				},
-			},
-		},
-	}
-}
-
-func TestSendFails(t *testing.T) {
-	stateDB := dbm.NewDB("state", dbBackend, dbDir)
-	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
-	genDoc.Accounts[1].Permissions.Base.Set(ptypes.Send, true)
-	genDoc.Accounts[2].Permissions.Base.Set(ptypes.Call, true)
-	genDoc.Accounts[3].Permissions.Base.Set(ptypes.CreateContract, true)
-	st := MakeGenesisState(stateDB, &genDoc)
-	blockCache := NewBlockCache(st)
-
-	//-------------------
-	// send txs
-
-	// simple send tx should fail
-	tx := txs.NewSendTx()
-	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	tx.AddOutput(user[1].Address, 5)
-	tx.SignInput(chainID, 0, user[0])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err == nil {
-		t.Fatal("Expected error")
-	} else {
-		fmt.Println(err)
-	}
-
-	// simple send tx with call perm should fail
-	tx = txs.NewSendTx()
-	if err := tx.AddInput(blockCache, user[2].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	tx.AddOutput(user[4].Address, 5)
-	tx.SignInput(chainID, 0, user[2])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err == nil {
-		t.Fatal("Expected error")
-	} else {
-		fmt.Println(err)
-	}
-
-	// simple send tx with create perm should fail
-	tx = txs.NewSendTx()
-	if err := tx.AddInput(blockCache, user[3].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	tx.AddOutput(user[4].Address, 5)
-	tx.SignInput(chainID, 0, user[3])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err == nil {
-		t.Fatal("Expected error")
-	} else {
-		fmt.Println(err)
-	}
-
-	// simple send tx to unknown account without create_account perm should fail
-	acc := blockCache.GetAccount(user[3].Address)
-	acc.Permissions.Base.Set(ptypes.Send, true)
-	blockCache.UpdateAccount(acc)
-	tx = txs.NewSendTx()
-	if err := tx.AddInput(blockCache, user[3].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	tx.AddOutput(user[6].Address, 5)
-	tx.SignInput(chainID, 0, user[3])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err == nil {
-		t.Fatal("Expected error")
-	} else {
-		fmt.Println(err)
-	}
-}
-
-func TestName(t *testing.T) {
-	stateDB := dbm.NewDB("state", dbBackend, dbDir)
-	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
-	genDoc.Accounts[0].Permissions.Base.Set(ptypes.Send, true)
-	genDoc.Accounts[1].Permissions.Base.Set(ptypes.Name, true)
-	st := MakeGenesisState(stateDB, &genDoc)
-	blockCache := NewBlockCache(st)
-
-	//-------------------
-	// name txs
-
-	// simple name tx without perm should fail
-	tx, err := txs.NewNameTx(st, user[0].PubKey, "somename", "somedata", 10000, 100)
-	if err != nil {
-		t.Fatal(err)
-	}
-	tx.Sign(chainID, user[0])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err == nil {
-		t.Fatal("Expected error")
-	} else {
-		fmt.Println(err)
-	}
-
-	// simple name tx with perm should pass
-	tx, err = txs.NewNameTx(st, user[1].PubKey, "somename", "somedata", 10000, 100)
-	if err != nil {
-		t.Fatal(err)
-	}
-	tx.Sign(chainID, user[1])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err != nil {
-		t.Fatal(err)
-	}
-}
-
-func TestCallFails(t *testing.T) {
-	stateDB := dbm.NewDB("state", dbBackend, dbDir)
-	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
-	genDoc.Accounts[1].Permissions.Base.Set(ptypes.Send, true)
-	genDoc.Accounts[2].Permissions.Base.Set(ptypes.Call, true)
-	genDoc.Accounts[3].Permissions.Base.Set(ptypes.CreateContract, true)
-	st := MakeGenesisState(stateDB, &genDoc)
-	blockCache := NewBlockCache(st)
-
-	//-------------------
-	// call txs
-
-	// simple call tx should fail
-	tx, _ := txs.NewCallTx(blockCache, user[0].PubKey, user[4].Address, nil, 100, 100, 100)
-	tx.Sign(chainID, user[0])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err == nil {
-		t.Fatal("Expected error")
-	} else {
-		fmt.Println(err)
-	}
-
-	// simple call tx with send permission should fail
-	tx, _ = txs.NewCallTx(blockCache, user[1].PubKey, user[4].Address, nil, 100, 100, 100)
-	tx.Sign(chainID, user[1])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err == nil {
-		t.Fatal("Expected error")
-	} else {
-		fmt.Println(err)
-	}
-
-	// simple call tx with create permission should fail
-	tx, _ = txs.NewCallTx(blockCache, user[3].PubKey, user[4].Address, nil, 100, 100, 100)
-	tx.Sign(chainID, user[3])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err == nil {
-		t.Fatal("Expected error")
-	} else {
-		fmt.Println(err)
-	}
-
-	//-------------------
-	// create txs
-
-	// simple call create tx should fail
-	tx, _ = txs.NewCallTx(blockCache, user[0].PubKey, nil, nil, 100, 100, 100)
-	tx.Sign(chainID, user[0])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err == nil {
-		t.Fatal("Expected error")
-	} else {
-		fmt.Println(err)
-	}
-
-	// simple call create tx with send perm should fail
-	tx, _ = txs.NewCallTx(blockCache, user[1].PubKey, nil, nil, 100, 100, 100)
-	tx.Sign(chainID, user[1])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err == nil {
-		t.Fatal("Expected error")
-	} else {
-		fmt.Println(err)
-	}
-
-	// simple call create tx with call perm should fail
-	tx, _ = txs.NewCallTx(blockCache, user[2].PubKey, nil, nil, 100, 100, 100)
-	tx.Sign(chainID, user[2])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err == nil {
-		t.Fatal("Expected error")
-	} else {
-		fmt.Println(err)
-	}
-}
-
-func TestSendPermission(t *testing.T) {
-	stateDB := dbm.NewDB("state", dbBackend, dbDir)
-	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
-	genDoc.Accounts[0].Permissions.Base.Set(ptypes.Send, true) // give the 0 account permission
-	st := MakeGenesisState(stateDB, &genDoc)
-	blockCache := NewBlockCache(st)
-
-	// A single input, having the permission, should succeed
-	tx := txs.NewSendTx()
-	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	tx.AddOutput(user[1].Address, 5)
-	tx.SignInput(chainID, 0, user[0])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err != nil {
-		t.Fatal("Transaction failed", err)
-	}
-
-	// Two inputs, one with permission, one without, should fail
-	tx = txs.NewSendTx()
-	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	if err := tx.AddInput(blockCache, user[1].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	tx.AddOutput(user[2].Address, 10)
-	tx.SignInput(chainID, 0, user[0])
-	tx.SignInput(chainID, 1, user[1])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err == nil {
-		t.Fatal("Expected error")
-	} else {
-		fmt.Println(err)
-	}
-}
-
-func TestCallPermission(t *testing.T) {
-	stateDB := dbm.NewDB("state", dbBackend, dbDir)
-	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
-	genDoc.Accounts[0].Permissions.Base.Set(ptypes.Call, true) // give the 0 account permission
-	st := MakeGenesisState(stateDB, &genDoc)
-	blockCache := NewBlockCache(st)
-
-	//------------------------------
-	// call to simple contract
-	fmt.Println("\n##### SIMPLE CONTRACT")
-
-	// create simple contract
-	simpleContractAddr := NewContractAddress(user[0].Address, 100)
-	simpleAcc := &acm.Account{
-		Address:     simpleContractAddr,
-		Balance:     0,
-		Code:        []byte{0x60},
-		Sequence:    0,
-		StorageRoot: Zero256.Bytes(),
-		Permissions: ptypes.ZeroAccountPermissions,
-	}
-	st.UpdateAccount(simpleAcc)
-
-	// A single input, having the permission, should succeed
-	tx, _ := txs.NewCallTx(blockCache, user[0].PubKey, simpleContractAddr, nil, 100, 100, 100)
-	tx.Sign(chainID, user[0])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err != nil {
-		t.Fatal("Transaction failed", err)
-	}
-
-	//----------------------------------------------------------
-	// call to contract that calls simple contract - without perm
-	fmt.Println("\n##### CALL TO SIMPLE CONTRACT (FAIL)")
-
-	// create contract that calls the simple contract
-	contractCode := callContractCode(simpleContractAddr)
-	caller1ContractAddr := NewContractAddress(user[0].Address, 101)
-	caller1Acc := &acm.Account{
-		Address:     caller1ContractAddr,
-		Balance:     10000,
-		Code:        contractCode,
-		Sequence:    0,
-		StorageRoot: Zero256.Bytes(),
-		Permissions: ptypes.ZeroAccountPermissions,
-	}
-	blockCache.UpdateAccount(caller1Acc)
-
-	// A single input, having the permission, but the contract doesn't have permission
-	tx, _ = txs.NewCallTx(blockCache, user[0].PubKey, caller1ContractAddr, nil, 100, 10000, 100)
-	tx.Sign(chainID, user[0])
-
-	// we need to subscribe to the Call event to detect the exception
-	_, exception := execTxWaitEvent(t, blockCache, tx, txs.EventStringAccCall(caller1ContractAddr)) //
-	if exception == "" {
-		t.Fatal("Expected exception")
-	}
-
-	//----------------------------------------------------------
-	// call to contract that calls simple contract - with perm
-	fmt.Println("\n##### CALL TO SIMPLE CONTRACT (PASS)")
-
-	// A single input, having the permission, and the contract has permission
-	caller1Acc.Permissions.Base.Set(ptypes.Call, true)
-	blockCache.UpdateAccount(caller1Acc)
-	tx, _ = txs.NewCallTx(blockCache, user[0].PubKey, caller1ContractAddr, nil, 100, 10000, 100)
-	tx.Sign(chainID, user[0])
-
-	// we need to subscribe to the Call event to detect the exception
-	_, exception = execTxWaitEvent(t, blockCache, tx, txs.EventStringAccCall(caller1ContractAddr)) //
-	if exception != "" {
-		t.Fatal("Unexpected exception:", exception)
-	}
-
-	//----------------------------------------------------------
-	// call to contract that calls contract that calls simple contract - without perm
-	// caller1Contract calls simpleContract. caller2Contract calls caller1Contract.
-	// caller1Contract does not have call perms, but caller2Contract does.
-	fmt.Println("\n##### CALL TO CONTRACT CALLING SIMPLE CONTRACT (FAIL)")
-
-	contractCode2 := callContractCode(caller1ContractAddr)
-	caller2ContractAddr := NewContractAddress(user[0].Address, 102)
-	caller2Acc := &acm.Account{
-		Address:     caller2ContractAddr,
-		Balance:     1000,
-		Code:        contractCode2,
-		Sequence:    0,
-		StorageRoot: Zero256.Bytes(),
-		Permissions: ptypes.ZeroAccountPermissions,
-	}
-	caller1Acc.Permissions.Base.Set(ptypes.Call, false)
-	caller2Acc.Permissions.Base.Set(ptypes.Call, true)
-	blockCache.UpdateAccount(caller1Acc)
-	blockCache.UpdateAccount(caller2Acc)
-
-	tx, _ = txs.NewCallTx(blockCache, user[0].PubKey, caller2ContractAddr, nil, 100, 10000, 100)
-	tx.Sign(chainID, user[0])
-
-	// we need to subscribe to the Call event to detect the exception
-	_, exception = execTxWaitEvent(t, blockCache, tx, txs.EventStringAccCall(caller1ContractAddr)) //
-	if exception == "" {
-		t.Fatal("Expected exception")
-	}
-
-	//----------------------------------------------------------
-	// call to contract that calls contract that calls simple contract - without perm
-	// caller1Contract calls simpleContract. caller2Contract calls caller1Contract.
-	// both caller1 and caller2 have permission
-	fmt.Println("\n##### CALL TO CONTRACT CALLING SIMPLE CONTRACT (PASS)")
-
-	caller1Acc.Permissions.Base.Set(ptypes.Call, true)
-	blockCache.UpdateAccount(caller1Acc)
-
-	tx, _ = txs.NewCallTx(blockCache, user[0].PubKey, caller2ContractAddr, nil, 100, 10000, 100)
-	tx.Sign(chainID, user[0])
-
-	// we need to subscribe to the Call event to detect the exception
-	_, exception = execTxWaitEvent(t, blockCache, tx, txs.EventStringAccCall(caller1ContractAddr)) //
-	if exception != "" {
-		t.Fatal("Unexpected exception", exception)
-	}
-}
-
-func TestCreatePermission(t *testing.T) {
-	stateDB := dbm.NewDB("state", dbBackend, dbDir)
-	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
-	genDoc.Accounts[0].Permissions.Base.Set(ptypes.CreateContract, true) // give the 0 account permission
-	genDoc.Accounts[0].Permissions.Base.Set(ptypes.Call, true)           // give the 0 account permission
-	st := MakeGenesisState(stateDB, &genDoc)
-	blockCache := NewBlockCache(st)
-
-	//------------------------------
-	// create a simple contract
-	fmt.Println("\n##### CREATE SIMPLE CONTRACT")
-
-	contractCode := []byte{0x60}
-	createCode := wrapContractForCreate(contractCode)
-
-	// A single input, having the permission, should succeed
-	tx, _ := txs.NewCallTx(blockCache, user[0].PubKey, nil, createCode, 100, 100, 100)
-	tx.Sign(chainID, user[0])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err != nil {
-		t.Fatal("Transaction failed", err)
-	}
-	// ensure the contract is there
-	contractAddr := NewContractAddress(tx.Input.Address, tx.Input.Sequence)
-	contractAcc := blockCache.GetAccount(contractAddr)
-	if contractAcc == nil {
-		t.Fatalf("failed to create contract %X", contractAddr)
-	}
-	if !bytes.Equal(contractAcc.Code, contractCode) {
-		t.Fatalf("contract does not have correct code. Got %X, expected %X", contractAcc.Code, contractCode)
-	}
-
-	//------------------------------
-	// create contract that uses the CREATE op
-	fmt.Println("\n##### CREATE FACTORY")
-
-	contractCode = []byte{0x60}
-	createCode = wrapContractForCreate(contractCode)
-	factoryCode := createContractCode()
-	createFactoryCode := wrapContractForCreate(factoryCode)
-
-	// A single input, having the permission, should succeed
-	tx, _ = txs.NewCallTx(blockCache, user[0].PubKey, nil, createFactoryCode, 100, 100, 100)
-	tx.Sign(chainID, user[0])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err != nil {
-		t.Fatal("Transaction failed", err)
-	}
-	// ensure the contract is there
-	contractAddr = NewContractAddress(tx.Input.Address, tx.Input.Sequence)
-	contractAcc = blockCache.GetAccount(contractAddr)
-	if contractAcc == nil {
-		t.Fatalf("failed to create contract %X", contractAddr)
-	}
-	if !bytes.Equal(contractAcc.Code, factoryCode) {
-		t.Fatalf("contract does not have correct code. Got %X, expected %X", contractAcc.Code, factoryCode)
-	}
-
-	//------------------------------
-	// call the contract (should FAIL)
-	fmt.Println("\n###### CALL THE FACTORY (FAIL)")
-
-	// A single input, having the permission, should succeed
-	tx, _ = txs.NewCallTx(blockCache, user[0].PubKey, contractAddr, createCode, 100, 100, 100)
-	tx.Sign(chainID, user[0])
-	// we need to subscribe to the Call event to detect the exception
-	_, exception := execTxWaitEvent(t, blockCache, tx, txs.EventStringAccCall(contractAddr)) //
-	if exception == "" {
-		t.Fatal("expected exception")
-	}
-
-	//------------------------------
-	// call the contract (should PASS)
-	fmt.Println("\n###### CALL THE FACTORY (PASS)")
-
-	contractAcc.Permissions.Base.Set(ptypes.CreateContract, true)
-	blockCache.UpdateAccount(contractAcc)
-
-	// A single input, having the permission, should succeed
-	tx, _ = txs.NewCallTx(blockCache, user[0].PubKey, contractAddr, createCode, 100, 100, 100)
-	tx.Sign(chainID, user[0])
-	// we need to subscribe to the Call event to detect the exception
-	_, exception = execTxWaitEvent(t, blockCache, tx, txs.EventStringAccCall(contractAddr)) //
-	if exception != "" {
-		t.Fatal("unexpected exception", exception)
-	}
-
-	//--------------------------------
-	fmt.Println("\n##### CALL to empty address")
-	zeroAddr := LeftPadBytes([]byte{}, 20)
-	code := callContractCode(zeroAddr)
-
-	contractAddr = NewContractAddress(user[0].Address, 110)
-	contractAcc = &acm.Account{
-		Address:     contractAddr,
-		Balance:     1000,
-		Code:        code,
-		Sequence:    0,
-		StorageRoot: Zero256.Bytes(),
-		Permissions: ptypes.ZeroAccountPermissions,
-	}
-	contractAcc.Permissions.Base.Set(ptypes.Call, true)
-	contractAcc.Permissions.Base.Set(ptypes.CreateContract, true)
-	blockCache.UpdateAccount(contractAcc)
-
-	// this should call the 0 address but not create ...
-	tx, _ = txs.NewCallTx(blockCache, user[0].PubKey, contractAddr, createCode, 100, 10000, 100)
-	tx.Sign(chainID, user[0])
-	// we need to subscribe to the Call event to detect the exception
-	_, exception = execTxWaitEvent(t, blockCache, tx, txs.EventStringAccCall(zeroAddr)) //
-	if exception != "" {
-		t.Fatal("unexpected exception", exception)
-	}
-	zeroAcc := blockCache.GetAccount(zeroAddr)
-	if len(zeroAcc.Code) != 0 {
-		t.Fatal("the zero account was given code from a CALL!")
-	}
-}
-
-/* TODO
-func TestBondPermission(t *testing.T) {
-	stateDB := dbm.NewDB("state",dbBackend,dbDir)
-	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
-	st := MakeGenesisState(stateDB, &genDoc)
-	blockCache := NewBlockCache(st)
-	var bondAcc *acm.Account
-
-	//------------------------------
-	// one bonder without permission should fail
-	tx, _ := txs.NewBondTx(user[1].PubKey)
-	if err := tx.AddInput(blockCache, user[1].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	tx.AddOutput(user[1].Address, 5)
-	tx.SignInput(chainID, 0, user[1])
-	tx.SignBond(chainID, user[1])
-	if err := ExecTx(blockCache, tx, true, nil); err == nil {
-		t.Fatal("Expected error")
-	} else {
-		fmt.Println(err)
-	}
-
-	//------------------------------
-	// one bonder with permission should pass
-	bondAcc = blockCache.GetAccount(user[1].Address)
-	bondAcc.Permissions.Base.Set(ptypes.Bond, true)
-	blockCache.UpdateAccount(bondAcc)
-	if err := ExecTx(blockCache, tx, true, nil); err != nil {
-		t.Fatal("Unexpected error", err)
-	}
-
-	// reset state (we can only bond with an account once ..)
-	genDoc = newBaseGenDoc(PermsAllFalse, PermsAllFalse)
-	st = MakeGenesisState(stateDB, &genDoc)
-	blockCache = NewBlockCache(st)
-	bondAcc = blockCache.GetAccount(user[1].Address)
-	bondAcc.Permissions.Base.Set(ptypes.Bond, true)
-	blockCache.UpdateAccount(bondAcc)
-	//------------------------------
-	// one bonder with permission and an input without send should fail
-	tx, _ = txs.NewBondTx(user[1].PubKey)
-	if err := tx.AddInput(blockCache, user[2].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	tx.AddOutput(user[1].Address, 5)
-	tx.SignInput(chainID, 0, user[2])
-	tx.SignBond(chainID, user[1])
-	if err := ExecTx(blockCache, tx, true, nil); err == nil {
-		t.Fatal("Expected error")
-	} else {
-		fmt.Println(err)
-	}
-
-	// reset state (we can only bond with an account once ..)
-	genDoc = newBaseGenDoc(PermsAllFalse, PermsAllFalse)
-	st = MakeGenesisState(stateDB, &genDoc)
-	blockCache = NewBlockCache(st)
-	bondAcc = blockCache.GetAccount(user[1].Address)
-	bondAcc.Permissions.Base.Set(ptypes.Bond, true)
-	blockCache.UpdateAccount(bondAcc)
-	//------------------------------
-	// one bonder with permission and an input with send should pass
-	sendAcc := blockCache.GetAccount(user[2].Address)
-	sendAcc.Permissions.Base.Set(ptypes.Send, true)
-	blockCache.UpdateAccount(sendAcc)
-	tx, _ = txs.NewBondTx(user[1].PubKey)
-	if err := tx.AddInput(blockCache, user[2].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	tx.AddOutput(user[1].Address, 5)
-	tx.SignInput(chainID, 0, user[2])
-	tx.SignBond(chainID, user[1])
-	if err := ExecTx(blockCache, tx, true, nil); err != nil {
-		t.Fatal("Unexpected error", err)
-	}
-
-	// reset state (we can only bond with an account once ..)
-	genDoc = newBaseGenDoc(PermsAllFalse, PermsAllFalse)
-	st = MakeGenesisState(stateDB, &genDoc)
-	blockCache = NewBlockCache(st)
-	bondAcc = blockCache.GetAccount(user[1].Address)
-	bondAcc.Permissions.Base.Set(ptypes.Bond, true)
-	blockCache.UpdateAccount(bondAcc)
-	//------------------------------
-	// one bonder with permission and an input with bond should pass
-	sendAcc.Permissions.Base.Set(ptypes.Bond, true)
-	blockCache.UpdateAccount(sendAcc)
-	tx, _ = txs.NewBondTx(user[1].PubKey)
-	if err := tx.AddInput(blockCache, user[2].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	tx.AddOutput(user[1].Address, 5)
-	tx.SignInput(chainID, 0, user[2])
-	tx.SignBond(chainID, user[1])
-	if err := ExecTx(blockCache, tx, true, nil); err != nil {
-		t.Fatal("Unexpected error", err)
-	}
-
-	// reset state (we can only bond with an account once ..)
-	genDoc = newBaseGenDoc(PermsAllFalse, PermsAllFalse)
-	st = MakeGenesisState(stateDB, &genDoc)
-	blockCache = NewBlockCache(st)
-	bondAcc = blockCache.GetAccount(user[1].Address)
-	bondAcc.Permissions.Base.Set(ptypes.Bond, true)
-	blockCache.UpdateAccount(bondAcc)
-	//------------------------------
-	// one bonder with permission and an input from that bonder and an input without send or bond should fail
-	tx, _ = txs.NewBondTx(user[1].PubKey)
-	if err := tx.AddInput(blockCache, user[1].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	if err := tx.AddInput(blockCache, user[2].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	tx.AddOutput(user[1].Address, 5)
-	tx.SignInput(chainID, 0, user[1])
-	tx.SignInput(chainID, 1, user[2])
-	tx.SignBond(chainID, user[1])
-	if err := ExecTx(blockCache, tx, true, nil); err == nil {
-		t.Fatal("Expected error")
-	}
-}
-*/
-
-func TestCreateAccountPermission(t *testing.T) {
-	stateDB := dbm.NewDB("state", dbBackend, dbDir)
-	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
-	genDoc.Accounts[0].Permissions.Base.Set(ptypes.Send, true)          // give the 0 account permission
-	genDoc.Accounts[1].Permissions.Base.Set(ptypes.Send, true)          // give the 0 account permission
-	genDoc.Accounts[0].Permissions.Base.Set(ptypes.CreateAccount, true) // give the 0 account permission
-	st := MakeGenesisState(stateDB, &genDoc)
-	blockCache := NewBlockCache(st)
-
-	//----------------------------------------------------------
-	// SendTx to unknown account
-
-	// A single input, having the permission, should succeed
-	tx := txs.NewSendTx()
-	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	tx.AddOutput(user[6].Address, 5)
-	tx.SignInput(chainID, 0, user[0])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err != nil {
-		t.Fatal("Transaction failed", err)
-	}
-
-	// Two inputs, both with send, one with create, one without, should fail
-	tx = txs.NewSendTx()
-	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	if err := tx.AddInput(blockCache, user[1].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	tx.AddOutput(user[7].Address, 10)
-	tx.SignInput(chainID, 0, user[0])
-	tx.SignInput(chainID, 1, user[1])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err == nil {
-		t.Fatal("Expected error")
-	} else {
-		fmt.Println(err)
-	}
-
-	// Two inputs, both with send, one with create, one without, two ouputs (one known, one unknown) should fail
-	tx = txs.NewSendTx()
-	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	if err := tx.AddInput(blockCache, user[1].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	tx.AddOutput(user[7].Address, 4)
-	tx.AddOutput(user[4].Address, 6)
-	tx.SignInput(chainID, 0, user[0])
-	tx.SignInput(chainID, 1, user[1])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err == nil {
-		t.Fatal("Expected error")
-	} else {
-		fmt.Println(err)
-	}
-
-	// Two inputs, both with send, both with create, should pass
-	acc := blockCache.GetAccount(user[1].Address)
-	acc.Permissions.Base.Set(ptypes.CreateAccount, true)
-	blockCache.UpdateAccount(acc)
-	tx = txs.NewSendTx()
-	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	if err := tx.AddInput(blockCache, user[1].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	tx.AddOutput(user[7].Address, 10)
-	tx.SignInput(chainID, 0, user[0])
-	tx.SignInput(chainID, 1, user[1])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err != nil {
-		t.Fatal("Unexpected error", err)
-	}
-
-	// Two inputs, both with send, both with create, two outputs (one known, one unknown) should pass
-	tx = txs.NewSendTx()
-	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	if err := tx.AddInput(blockCache, user[1].PubKey, 5); err != nil {
-		t.Fatal(err)
-	}
-	tx.AddOutput(user[7].Address, 7)
-	tx.AddOutput(user[4].Address, 3)
-	tx.SignInput(chainID, 0, user[0])
-	tx.SignInput(chainID, 1, user[1])
-	if err := ExecTx(blockCache, tx, true, nil, logger); err != nil {
-		t.Fatal("Unexpected error", err)
-	}
-
-	//----------------------------------------------------------
-	// CALL to unknown account
-
-	acc = blockCache.GetAccount(user[0].Address)
-	acc.Permissions.Base.Set(ptypes.Call, true)
-	blockCache.UpdateAccount(acc)
-
-	// call to contract that calls unknown account - without create_account perm
-	// create contract that calls the simple contract
-	contractCode := callContractCode(user[9].Address)
-	caller1ContractAddr := NewContractAddress(user[4].Address, 101)
-	caller1Acc := &acm.Account{
-		Address:     caller1ContractAddr,
-		Balance:     0,
-		Code:        contractCode,
-		Sequence:    0,
-		StorageRoot: Zero256.Bytes(),
-		Permissions: ptypes.ZeroAccountPermissions,
-	}
-	blockCache.UpdateAccount(caller1Acc)
-
-	// A single input, having the permission, but the contract doesn't have permission
-	txCall, _ := txs.NewCallTx(blockCache, user[0].PubKey, caller1ContractAddr, nil, 100, 10000, 100)
-	txCall.Sign(chainID, user[0])
-
-	// we need to subscribe to the Call event to detect the exception
-	_, exception := execTxWaitEvent(t, blockCache, txCall, txs.EventStringAccCall(caller1ContractAddr)) //
-	if exception == "" {
-		t.Fatal("Expected exception")
-	}
-
-	// NOTE: for a contract to be able to CreateAccount, it must be able to call
-	// NOTE: for a user to be able to CreateAccount, it must be able to send!
-	caller1Acc.Permissions.Base.Set(ptypes.CreateAccount, true)
-	caller1Acc.Permissions.Base.Set(ptypes.Call, true)
-	blockCache.UpdateAccount(caller1Acc)
-	// A single input, having the permission, but the contract doesn't have permission
-	txCall, _ = txs.NewCallTx(blockCache, user[0].PubKey, caller1ContractAddr, nil, 100, 10000, 100)
-	txCall.Sign(chainID, user[0])
-
-	// we need to subscribe to the Call event to detect the exception
-	_, exception = execTxWaitEvent(t, blockCache, txCall, txs.EventStringAccCall(caller1ContractAddr)) //
-	if exception != "" {
-		t.Fatal("Unexpected exception", exception)
-	}
-
-}
-
-// holla at my boy
-var DougAddress = append([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, []byte("THISISDOUG")...)
-
-func TestSNativeCALL(t *testing.T) {
-	stateDB := dbm.NewDB("state", dbBackend, dbDir)
-	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
-	genDoc.Accounts[0].Permissions.Base.Set(ptypes.Call, true) // give the 0 account permission
-	genDoc.Accounts[3].Permissions.Base.Set(ptypes.Bond, true) // some arbitrary permission to play with
-	genDoc.Accounts[3].Permissions.AddRole("bumble")
-	genDoc.Accounts[3].Permissions.AddRole("bee")
-	st := MakeGenesisState(stateDB, &genDoc)
-	blockCache := NewBlockCache(st)
-
-	//----------------------------------------------------------
-	// Test CALL to SNative contracts
-
-	// make the main contract once
-	doug := &acm.Account{
-		Address:     DougAddress,
-		Balance:     0,
-		Code:        nil,
-		Sequence:    0,
-		StorageRoot: Zero256.Bytes(),
-		Permissions: ptypes.ZeroAccountPermissions,
-	}
-	doug.Permissions.Base.Set(ptypes.Call, true)
-	//doug.Permissions.Base.Set(ptypes.HasBase, true)
-	blockCache.UpdateAccount(doug)
-
-	fmt.Println("\n#### HasBase")
-	// HasBase
-	snativeAddress, pF, data := snativePermTestInputCALL("hasBase", user[3], ptypes.Bond, false)
-	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
-	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error {
-		// return value should be true or false as a 32 byte array...
-		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
-			return fmt.Errorf("Expected 1. Got %X", ret)
-		}
-		return nil
-	})
-
-	fmt.Println("\n#### SetBase")
-	// SetBase
-	snativeAddress, pF, data = snativePermTestInputCALL("setBase", user[3], ptypes.Bond, false)
-	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
-	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
-	snativeAddress, pF, data = snativePermTestInputCALL("hasBase", user[3], ptypes.Bond, false)
-	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error {
-		// return value should be true or false as a 32 byte array...
-		if !IsZeros(ret) {
-			return fmt.Errorf("Expected 0. Got %X", ret)
-		}
-		return nil
-	})
-	snativeAddress, pF, data = snativePermTestInputCALL("setBase", user[3], ptypes.CreateContract, true)
-	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
-	snativeAddress, pF, data = snativePermTestInputCALL("hasBase", user[3], ptypes.CreateContract, false)
-	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error {
-		// return value should be true or false as a 32 byte array...
-		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
-			return fmt.Errorf("Expected 1. Got %X", ret)
-		}
-		return nil
-	})
-
-	fmt.Println("\n#### UnsetBase")
-	// UnsetBase
-	snativeAddress, pF, data = snativePermTestInputCALL("unsetBase", user[3], ptypes.CreateContract, false)
-	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
-	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
-	snativeAddress, pF, data = snativePermTestInputCALL("hasBase", user[3], ptypes.CreateContract, false)
-	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error {
-		if !IsZeros(ret) {
-			return fmt.Errorf("Expected 0. Got %X", ret)
-		}
-		return nil
-	})
-
-	fmt.Println("\n#### SetGlobal")
-	// SetGlobalPerm
-	snativeAddress, pF, data = snativePermTestInputCALL("setGlobal", user[3], ptypes.CreateContract, true)
-	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
-	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
-	snativeAddress, pF, data = snativePermTestInputCALL("hasBase", user[3], ptypes.CreateContract, false)
-	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error {
-		// return value should be true or false as a 32 byte array...
-		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
-			return fmt.Errorf("Expected 1. Got %X", ret)
-		}
-		return nil
-	})
-
-	fmt.Println("\n#### HasRole")
-	// HasRole
-	snativeAddress, pF, data = snativeRoleTestInputCALL("hasRole", user[3], "bumble")
-	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
-	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error {
-		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
-			return fmt.Errorf("Expected 1. Got %X", ret)
-		}
-		return nil
-	})
-
-	fmt.Println("\n#### AddRole")
-	// AddRole
-	snativeAddress, pF, data = snativeRoleTestInputCALL("hasRole", user[3], "chuck")
-	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error {
-		if !IsZeros(ret) {
-			return fmt.Errorf("Expected 0. Got %X", ret)
-		}
-		return nil
-	})
-	snativeAddress, pF, data = snativeRoleTestInputCALL("addRole", user[3], "chuck")
-	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
-	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
-	snativeAddress, pF, data = snativeRoleTestInputCALL("hasRole", user[3], "chuck")
-	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error {
-		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
-			return fmt.Errorf("Expected 1. Got %X", ret)
-		}
-		return nil
-	})
-
-	fmt.Println("\n#### RmRole")
-	// RmRole
-	snativeAddress, pF, data = snativeRoleTestInputCALL("removeRole", user[3], "chuck")
-	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
-	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
-	snativeAddress, pF, data = snativeRoleTestInputCALL("hasRole", user[3], "chuck")
-	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error {
-		if !IsZeros(ret) {
-			return fmt.Errorf("Expected 0. Got %X", ret)
-		}
-		return nil
-	})
-}
-
-func TestSNativeTx(t *testing.T) {
-	stateDB := dbm.NewDB("state", dbBackend, dbDir)
-	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
-	genDoc.Accounts[0].Permissions.Base.Set(ptypes.Call, true) // give the 0 account permission
-	genDoc.Accounts[3].Permissions.Base.Set(ptypes.Bond, true) // some arbitrary permission to play with
-	genDoc.Accounts[3].Permissions.AddRole("bumble")
-	genDoc.Accounts[3].Permissions.AddRole("bee")
-	st := MakeGenesisState(stateDB, &genDoc)
-	blockCache := NewBlockCache(st)
-
-	//----------------------------------------------------------
-	// Test SNativeTx
-
-	fmt.Println("\n#### SetBase")
-	// SetBase
-	snativeArgs := snativePermTestInputTx("setBase", user[3], ptypes.Bond, false)
-	testSNativeTxExpectFail(t, blockCache, snativeArgs)
-	testSNativeTxExpectPass(t, blockCache, ptypes.SetBase, snativeArgs)
-	acc := blockCache.GetAccount(user[3].Address)
-	if v, _ := acc.Permissions.Base.Get(ptypes.Bond); v {
-		t.Fatal("expected permission to be set false")
-	}
-	snativeArgs = snativePermTestInputTx("setBase", user[3], ptypes.CreateContract, true)
-	testSNativeTxExpectPass(t, blockCache, ptypes.SetBase, snativeArgs)
-	acc = blockCache.GetAccount(user[3].Address)
-	if v, _ := acc.Permissions.Base.Get(ptypes.CreateContract); !v {
-		t.Fatal("expected permission to be set true")
-	}
-
-	fmt.Println("\n#### UnsetBase")
-	// UnsetBase
-	snativeArgs = snativePermTestInputTx("unsetBase", user[3], ptypes.CreateContract, false)
-	testSNativeTxExpectFail(t, blockCache, snativeArgs)
-	testSNativeTxExpectPass(t, blockCache, ptypes.UnsetBase, snativeArgs)
-	acc = blockCache.GetAccount(user[3].Address)
-	if v, _ := acc.Permissions.Base.Get(ptypes.CreateContract); v {
-		t.Fatal("expected permission to be set false")
-	}
-
-	fmt.Println("\n#### SetGlobal")
-	// SetGlobalPerm
-	snativeArgs = snativePermTestInputTx("setGlobal", user[3], ptypes.CreateContract, true)
-	testSNativeTxExpectFail(t, blockCache, snativeArgs)
-	testSNativeTxExpectPass(t, blockCache, ptypes.SetGlobal, snativeArgs)
-	acc = blockCache.GetAccount(ptypes.GlobalPermissionsAddress)
-	if v, _ := acc.Permissions.Base.Get(ptypes.CreateContract); !v {
-		t.Fatal("expected permission to be set true")
-	}
-
-	fmt.Println("\n#### AddRole")
-	// AddRole
-	snativeArgs = snativeRoleTestInputTx("addRole", user[3], "chuck")
-	testSNativeTxExpectFail(t, blockCache, snativeArgs)
-	testSNativeTxExpectPass(t, blockCache, ptypes.AddRole, snativeArgs)
-	acc = blockCache.GetAccount(user[3].Address)
-	if v := acc.Permissions.HasRole("chuck"); !v {
-		t.Fatal("expected role to be added")
-	}
-
-	fmt.Println("\n#### RmRole")
-	// RmRole
-	snativeArgs = snativeRoleTestInputTx("removeRole", user[3], "chuck")
-	testSNativeTxExpectFail(t, blockCache, snativeArgs)
-	testSNativeTxExpectPass(t, blockCache, ptypes.RmRole, snativeArgs)
-	acc = blockCache.GetAccount(user[3].Address)
-	if v := acc.Permissions.HasRole("chuck"); v {
-		t.Fatal("expected role to be removed")
-	}
-}
-
-//-------------------------------------------------------------------------------------
-// helpers
-
-var ExceptionTimeOut = "timed out waiting for event"
-
-// run ExecTx and wait for the Call event on given addr
-// returns the msg data and an error/exception
-func execTxWaitEvent(t *testing.T, blockCache *BlockCache, tx txs.Tx, eventid string) (interface{}, string) {
-	evsw := events.NewEventSwitch()
-	evsw.Start()
-	ch := make(chan interface{})
-	evsw.AddListenerForEvent("test", eventid, func(msg events.EventData) {
-		ch <- msg
-	})
-	evc := events.NewEventCache(evsw)
-	go func() {
-		if err := ExecTx(blockCache, tx, true, evc, logger); err != nil {
-			ch <- err.Error()
-		}
-		evc.Flush()
-	}()
-	ticker := time.NewTicker(5 * time.Second)
-	var msg interface{}
-	select {
-	case msg = <-ch:
-	case <-ticker.C:
-		return nil, ExceptionTimeOut
-	}
-
-	switch ev := msg.(type) {
-	case txs.EventDataTx:
-		return ev, ev.Exception
-	case txs.EventDataCall:
-		return ev, ev.Exception
-	case string:
-		return nil, ev
-	default:
-		return ev, ""
-	}
-}
-
-// give a contract perms for an snative, call it, it calls the snative, but shouldn't have permission
-func testSNativeCALLExpectFail(t *testing.T, blockCache *BlockCache, doug *acm.Account, snativeAddress, data []byte) {
-	testSNativeCALL(t, false, blockCache, doug, 0, snativeAddress, data, nil)
-}
-
-// give a contract perms for an snative, call it, it calls the snative, ensure the check funciton (f) succeeds
-func testSNativeCALLExpectPass(t *testing.T, blockCache *BlockCache, doug *acm.Account, snativePerm ptypes.PermFlag, snativeAddress, data []byte, f func([]byte) error) {
-	testSNativeCALL(t, true, blockCache, doug, snativePerm, snativeAddress, data, f)
-}
-
-func testSNativeCALL(t *testing.T, expectPass bool, blockCache *BlockCache, doug *acm.Account, snativePerm ptypes.PermFlag, snativeAddress, data []byte, f func([]byte) error) {
-	if expectPass {
-		doug.Permissions.Base.Set(snativePerm, true)
-	}
-	var addr []byte
-	contractCode := callContractCode(snativeAddress)
-	doug.Code = contractCode
-	blockCache.UpdateAccount(doug)
-	addr = doug.Address
-	tx, _ := txs.NewCallTx(blockCache, user[0].PubKey, addr, data, 100, 10000, 100)
-	tx.Sign(chainID, user[0])
-	fmt.Println("subscribing to", txs.EventStringAccCall(snativeAddress))
-	ev, exception := execTxWaitEvent(t, blockCache, tx, txs.EventStringAccCall(snativeAddress))
-	if exception == ExceptionTimeOut {
-		t.Fatal("Timed out waiting for event")
-	}
-	if expectPass {
-		if exception != "" {
-			t.Fatal("Unexpected exception", exception)
-		}
-		evv := ev.(txs.EventDataCall)
-		ret := evv.Return
-		if err := f(ret); err != nil {
-			t.Fatal(err)
-		}
-	} else {
-		if exception == "" {
-			t.Fatal("Expected exception")
-		}
-	}
-}
-
-func testSNativeTxExpectFail(t *testing.T, blockCache *BlockCache, snativeArgs ptypes.PermArgs) {
-	testSNativeTx(t, false, blockCache, 0, snativeArgs)
-}
-
-func testSNativeTxExpectPass(t *testing.T, blockCache *BlockCache, perm ptypes.PermFlag, snativeArgs ptypes.PermArgs) {
-	testSNativeTx(t, true, blockCache, perm, snativeArgs)
-}
-
-func testSNativeTx(t *testing.T, expectPass bool, blockCache *BlockCache, perm ptypes.PermFlag, snativeArgs ptypes.PermArgs) {
-	if expectPass {
-		acc := blockCache.GetAccount(user[0].Address)
-		acc.Permissions.Base.Set(perm, true)
-		blockCache.UpdateAccount(acc)
-	}
-	tx, _ := txs.NewPermissionsTx(blockCache, user[0].PubKey, snativeArgs)
-	tx.Sign(chainID, user[0])
-	err := ExecTx(blockCache, tx, true, nil, logger)
-	if expectPass {
-		if err != nil {
-			t.Fatal("Unexpected exception", err)
-		}
-	} else {
-		if err == nil {
-			t.Fatal("Expected exception")
-		}
-	}
-}
-
-func boolToWord256(v bool) Word256 {
-	var vint byte
-	if v {
-		vint = 0x1
-	} else {
-		vint = 0x0
-	}
-	return LeftPadWord256([]byte{vint})
-}
-
-func permNameToFuncID(name string) []byte {
-	function, err := permissionsContract.FunctionByName(name)
-	if err != nil {
-		panic("didn't find snative function signature!")
-	}
-	id := function.ID()
-	return id[:]
-}
-
-func snativePermTestInputCALL(name string, user *acm.PrivAccount, perm ptypes.PermFlag, val bool) (addr []byte, pF ptypes.PermFlag, data []byte) {
-	addr = permissionsContract.AddressBytes()
-	switch name {
-	case "hasBase", "unsetBase":
-		data = LeftPadBytes(user.Address, 32)
-		data = append(data, Uint64ToWord256(uint64(perm)).Bytes()...)
-	case "setBase":
-		data = LeftPadBytes(user.Address, 32)
-		data = append(data, Uint64ToWord256(uint64(perm)).Bytes()...)
-		data = append(data, boolToWord256(val).Bytes()...)
-	case "setGlobal":
-		data = Uint64ToWord256(uint64(perm)).Bytes()
-		data = append(data, boolToWord256(val).Bytes()...)
-	}
-	data = append(permNameToFuncID(name), data...)
-	var err error
-	if pF, err = ptypes.PermStringToFlag(name); err != nil {
-		panic(fmt.Sprintf("failed to convert perm string (%s) to flag", name))
-	}
-	return
-}
-
-func snativePermTestInputTx(name string, user *acm.PrivAccount, perm ptypes.PermFlag, val bool) (snativeArgs ptypes.PermArgs) {
-	switch name {
-	case "hasBase":
-		snativeArgs = &ptypes.HasBaseArgs{user.Address, perm}
-	case "unsetBase":
-		snativeArgs = &ptypes.UnsetBaseArgs{user.Address, perm}
-	case "setBase":
-		snativeArgs = &ptypes.SetBaseArgs{user.Address, perm, val}
-	case "setGlobal":
-		snativeArgs = &ptypes.SetGlobalArgs{perm, val}
-	}
-	return
-}
-
-func snativeRoleTestInputCALL(name string, user *acm.PrivAccount, role string) (addr []byte, pF ptypes.PermFlag, data []byte) {
-	addr = permissionsContract.AddressBytes()
-	data = LeftPadBytes(user.Address, 32)
-	data = append(data, RightPadBytes([]byte(role), 32)...)
-	data = append(permNameToFuncID(name), data...)
-
-	var err error
-	if pF, err = ptypes.PermStringToFlag(name); err != nil {
-		panic(fmt.Sprintf("failed to convert perm string (%s) to flag", name))
-	}
-	return
-}
-
-func snativeRoleTestInputTx(name string, user *acm.PrivAccount, role string) (snativeArgs ptypes.PermArgs) {
-	switch name {
-	case "hasRole":
-		snativeArgs = &ptypes.HasRoleArgs{user.Address, role}
-	case "addRole":
-		snativeArgs = &ptypes.AddRoleArgs{user.Address, role}
-	case "removeRole":
-		snativeArgs = &ptypes.RmRoleArgs{user.Address, role}
-	}
-	return
-}
-
-// convenience function for contract that calls a given address
-func callContractCode(contractAddr []byte) []byte {
-	// calldatacopy into mem and use as input to call
-	memOff, inputOff := byte(0x0), byte(0x0)
-	value := byte(0x1)
-	inOff := byte(0x0)
-	retOff, retSize := byte(0x0), byte(0x20)
-
-	// this is the code we want to run (call a contract and return)
-	return Bytecode(CALLDATASIZE, PUSH1, inputOff, PUSH1, memOff,
-		CALLDATACOPY, PUSH1, retSize, PUSH1, retOff, CALLDATASIZE, PUSH1, inOff,
-		PUSH1, value, PUSH20, contractAddr,
-		// Zeno loves us - call with half of the available gas each time we CALL
-		PUSH1, 2, GAS, DIV, CALL,
-		PUSH1, 32, PUSH1, 0, RETURN)
-}
-
-// convenience function for contract that is a factory for the code that comes as call data
-func createContractCode() []byte {
-	// TODO: gas ...
-
-	// calldatacopy the calldatasize
-	memOff, inputOff := byte(0x0), byte(0x0)
-	contractCode := []byte{0x60, memOff, 0x60, inputOff, 0x36, 0x37}
-
-	// create
-	value := byte(0x1)
-	contractCode = append(contractCode, []byte{0x60, value, 0x36, 0x60, memOff, 0xf0}...)
-	return contractCode
-}
-
-// wrap a contract in create code
-func wrapContractForCreate(contractCode []byte) []byte {
-	// the is the code we need to return the contractCode when the contract is initialized
-	lenCode := len(contractCode)
-	// push code to the stack
-	code := append([]byte{0x7f}, RightPadWord256(contractCode).Bytes()...)
-	// store it in memory
-	code = append(code, []byte{0x60, 0x0, 0x52}...)
-	// return whats in memory
-	code = append(code, []byte{0x60, byte(lenCode), 0x60, 0x0, 0xf3}...)
-	// return init code, contract code, expected return
-	return code
-}
diff --git a/manager/burrow-mint/state/tx_cache.go b/manager/burrow-mint/state/tx_cache.go
deleted file mode 100644
index d892f46e..00000000
--- a/manager/burrow-mint/state/tx_cache.go
+++ /dev/null
@@ -1,218 +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 state
-
-import (
-	"fmt"
-
-	acm "github.com/hyperledger/burrow/account"
-	"github.com/hyperledger/burrow/common/sanity"
-	"github.com/hyperledger/burrow/manager/burrow-mint/evm"
-	ptypes "github.com/hyperledger/burrow/permission/types" // for GlobalPermissionAddress ...
-	"github.com/hyperledger/burrow/txs"
-	. "github.com/hyperledger/burrow/word256"
-
-	"github.com/tendermint/go-crypto"
-)
-
-type TxCache struct {
-	backend  *BlockCache
-	accounts map[Word256]vmAccountInfo
-	storages map[Tuple256]Word256
-}
-
-var _ vm.AppState = &TxCache{}
-
-func NewTxCache(backend *BlockCache) *TxCache {
-	return &TxCache{
-		backend:  backend,
-		accounts: make(map[Word256]vmAccountInfo),
-		storages: make(map[Tuple256]Word256),
-	}
-}
-
-//-------------------------------------
-// TxCache.account
-
-func (cache *TxCache) GetAccount(addr Word256) *vm.Account {
-	acc, removed := cache.accounts[addr].unpack()
-	if removed {
-		return nil
-	} else if acc == nil {
-		acc2 := cache.backend.GetAccount(addr.Postfix(20))
-		if acc2 != nil {
-			return toVMAccount(acc2)
-		}
-	}
-	return acc
-}
-
-func (cache *TxCache) UpdateAccount(acc *vm.Account) {
-	addr := acc.Address
-	_, removed := cache.accounts[addr].unpack()
-	if removed {
-		sanity.PanicSanity("UpdateAccount on a removed account")
-	}
-	cache.accounts[addr] = vmAccountInfo{acc, false}
-}
-
-func (cache *TxCache) RemoveAccount(acc *vm.Account) {
-	addr := acc.Address
-	_, removed := cache.accounts[addr].unpack()
-	if removed {
-		sanity.PanicSanity("RemoveAccount on a removed account")
-	}
-	cache.accounts[addr] = vmAccountInfo{acc, true}
-}
-
-// Creates a 20 byte address and bumps the creator's nonce.
-func (cache *TxCache) CreateAccount(creator *vm.Account) *vm.Account {
-
-	// Generate an address
-	nonce := creator.Nonce
-	creator.Nonce += 1
-
-	addr := LeftPadWord256(NewContractAddress(creator.Address.Postfix(20), int(nonce)))
-
-	// Create account from address.
-	account, removed := cache.accounts[addr].unpack()
-	if removed || account == nil {
-		account = &vm.Account{
-			Address:     addr,
-			Balance:     0,
-			Code:        nil,
-			Nonce:       0,
-			Permissions: cache.GetAccount(ptypes.GlobalPermissionsAddress256).Permissions,
-			Other: vmAccountOther{
-				PubKey:      nil,
-				StorageRoot: nil,
-			},
-		}
-		cache.accounts[addr] = vmAccountInfo{account, false}
-		return account
-	} else {
-		// either we've messed up nonce handling, or sha3 is broken
-		sanity.PanicSanity(fmt.Sprintf("Could not create account, address already exists: %X", addr))
-		return nil
-	}
-}
-
-// TxCache.account
-//-------------------------------------
-// TxCache.storage
-
-func (cache *TxCache) GetStorage(addr Word256, key Word256) Word256 {
-	// Check cache
-	value, ok := cache.storages[Tuple256{addr, key}]
-	if ok {
-		return value
-	}
-
-	// Load from backend
-	return cache.backend.GetStorage(addr, key)
-}
-
-// NOTE: Set value to zero to removed from the trie.
-func (cache *TxCache) SetStorage(addr Word256, key Word256, value Word256) {
-	_, removed := cache.accounts[addr].unpack()
-	if removed {
-		sanity.PanicSanity("SetStorage() on a removed account")
-	}
-	cache.storages[Tuple256{addr, key}] = value
-}
-
-// TxCache.storage
-//-------------------------------------
-
-// These updates do not have to be in deterministic order,
-// the backend is responsible for ordering updates.
-func (cache *TxCache) Sync() {
-	// Remove or update storage
-	for addrKey, value := range cache.storages {
-		addr, key := Tuple256Split(addrKey)
-		cache.backend.SetStorage(addr, key, value)
-	}
-
-	// Remove or update accounts
-	for addr, accInfo := range cache.accounts {
-		acc, removed := accInfo.unpack()
-		if removed {
-			cache.backend.RemoveAccount(addr.Postfix(20))
-		} else {
-			cache.backend.UpdateAccount(toStateAccount(acc))
-		}
-	}
-}
-
-//-----------------------------------------------------------------------------
-
-// Convenience function to return address of new contract
-func NewContractAddress(caller []byte, nonce int) []byte {
-	return txs.NewContractAddress(caller, nonce)
-}
-
-// Converts backend.Account to vm.Account struct.
-func toVMAccount(acc *acm.Account) *vm.Account {
-	return &vm.Account{
-		Address:     LeftPadWord256(acc.Address),
-		Balance:     acc.Balance,
-		Code:        acc.Code, // This is crazy.
-		Nonce:       int64(acc.Sequence),
-		Permissions: acc.Permissions, // Copy
-		Other: vmAccountOther{
-			PubKey:      acc.PubKey,
-			StorageRoot: acc.StorageRoot,
-		},
-	}
-}
-
-// Converts vm.Account to backend.Account struct.
-func toStateAccount(acc *vm.Account) *acm.Account {
-	var pubKey crypto.PubKey
-	var storageRoot []byte
-	if acc.Other != nil {
-		pubKey, storageRoot = acc.Other.(vmAccountOther).unpack()
-	}
-
-	return &acm.Account{
-		Address:     acc.Address.Postfix(20),
-		PubKey:      pubKey,
-		Balance:     acc.Balance,
-		Code:        acc.Code,
-		Sequence:    int(acc.Nonce),
-		StorageRoot: storageRoot,
-		Permissions: acc.Permissions, // Copy
-	}
-}
-
-// Everything in acmAccount that doesn't belong in
-// exported vmAccount fields.
-type vmAccountOther struct {
-	PubKey      crypto.PubKey
-	StorageRoot []byte
-}
-
-func (accOther vmAccountOther) unpack() (crypto.PubKey, []byte) {
-	return accOther.PubKey, accOther.StorageRoot
-}
-
-type vmAccountInfo struct {
-	account *vm.Account
-	removed bool
-}
-
-func (accInfo vmAccountInfo) unpack() (*vm.Account, bool) {
-	return accInfo.account, accInfo.removed
-}
diff --git a/manager/burrow-mint/state/tx_cache_test.go b/manager/burrow-mint/state/tx_cache_test.go
deleted file mode 100644
index 4b30fa4a..00000000
--- a/manager/burrow-mint/state/tx_cache_test.go
+++ /dev/null
@@ -1,36 +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 state
-
-import (
-	"bytes"
-	"testing"
-
-	"github.com/tendermint/go-wire"
-)
-
-func TestStateToFromVMAccount(t *testing.T) {
-	acmAcc1, _ := RandAccount(true, 456)
-	vmAcc := toVMAccount(acmAcc1)
-	acmAcc2 := toStateAccount(vmAcc)
-
-	acmAcc1Bytes := wire.BinaryBytes(acmAcc1)
-	acmAcc2Bytes := wire.BinaryBytes(acmAcc2)
-	if !bytes.Equal(acmAcc1Bytes, acmAcc2Bytes) {
-		t.Errorf("Unexpected account wire bytes\n%X vs\n%X",
-			acmAcc1Bytes, acmAcc2Bytes)
-	}
-
-}
diff --git a/manager/burrow-mint/transactor.go b/manager/burrow-mint/transactor.go
deleted file mode 100644
index b4f16d89..00000000
--- a/manager/burrow-mint/transactor.go
+++ /dev/null
@@ -1,438 +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 burrowmint
-
-import (
-	"bytes"
-	"encoding/hex"
-	"fmt"
-	"sync"
-	"time"
-
-	"github.com/hyperledger/burrow/account"
-	core_types "github.com/hyperledger/burrow/core/types"
-	"github.com/hyperledger/burrow/event"
-	"github.com/hyperledger/burrow/manager/burrow-mint/evm"
-	"github.com/hyperledger/burrow/manager/burrow-mint/state"
-	"github.com/hyperledger/burrow/txs"
-	"github.com/hyperledger/burrow/word256"
-
-	"github.com/tendermint/go-crypto"
-	tEvents "github.com/tendermint/go-events"
-)
-
-// Transactor is part of the pipe for BurrowMint and provides the implementation
-// for the pipe to call into the BurrowMint application
-type transactor struct {
-	chainID       string
-	eventSwitch   tEvents.Fireable
-	burrowMint    *BurrowMint
-	eventEmitter  event.EventEmitter
-	txMtx         *sync.Mutex
-	txBroadcaster func(tx txs.Tx) error
-}
-
-func newTransactor(chainID string, eventSwitch tEvents.Fireable,
-	burrowMint *BurrowMint, eventEmitter event.EventEmitter,
-	txBroadcaster func(tx txs.Tx) error) *transactor {
-	return &transactor{
-		chainID,
-		eventSwitch,
-		burrowMint,
-		eventEmitter,
-		&sync.Mutex{},
-		txBroadcaster,
-	}
-}
-
-// Run a contract's code on an isolated and unpersisted state
-// Cannot be used to create new contracts
-// NOTE: this function is used from 1337 and has sibling on 46657
-// in pipe.go
-// TODO: [ben] resolve incompatibilities in byte representation for 0.12.0 release
-func (this *transactor) Call(fromAddress, toAddress, data []byte) (
-	*core_types.Call, error) {
-
-	st := this.burrowMint.GetState()
-	cache := state.NewBlockCache(st) // XXX: DON'T MUTATE THIS CACHE (used internally for CheckTx)
-	outAcc := cache.GetAccount(toAddress)
-	if outAcc == nil {
-		return nil, fmt.Errorf("Account %X does not exist", toAddress)
-	}
-	if fromAddress == nil {
-		fromAddress = []byte{}
-	}
-	callee := toVMAccount(outAcc)
-	caller := &vm.Account{Address: word256.LeftPadWord256(fromAddress)}
-	txCache := state.NewTxCache(cache)
-	gasLimit := st.GetGasLimit()
-	params := vm.Params{
-		BlockHeight: int64(st.LastBlockHeight),
-		BlockHash:   word256.LeftPadWord256(st.LastBlockHash),
-		BlockTime:   st.LastBlockTime.Unix(),
-		GasLimit:    gasLimit,
-	}
-
-	vmach := vm.NewVM(txCache, vm.DefaultDynamicMemoryProvider, params,
-		caller.Address, nil)
-	vmach.SetFireable(this.eventSwitch)
-	gas := gasLimit
-	ret, err := vmach.Call(caller, callee, callee.Code, data, 0, &gas)
-	if err != nil {
-		return nil, err
-	}
-	gasUsed := gasLimit - gas
-	// here return bytes are hex encoded; on the sibling function
-	// they are not
-	return &core_types.Call{Return: hex.EncodeToString(ret), GasUsed: gasUsed}, nil
-}
-
-// Run the given code on an isolated and unpersisted state
-// Cannot be used to create new contracts.
-func (this *transactor) CallCode(fromAddress, code, data []byte) (
-	*core_types.Call, error) {
-	if fromAddress == nil {
-		fromAddress = []byte{}
-	}
-	cache := this.burrowMint.GetCheckCache() // XXX: DON'T MUTATE THIS CACHE (used internally for CheckTx)
-	callee := &vm.Account{Address: word256.LeftPadWord256(fromAddress)}
-	caller := &vm.Account{Address: word256.LeftPadWord256(fromAddress)}
-	txCache := state.NewTxCache(cache)
-	st := this.burrowMint.GetState() // for block height, time
-	gasLimit := st.GetGasLimit()
-	params := vm.Params{
-		BlockHeight: int64(st.LastBlockHeight),
-		BlockHash:   word256.LeftPadWord256(st.LastBlockHash),
-		BlockTime:   st.LastBlockTime.Unix(),
-		GasLimit:    gasLimit,
-	}
-
-	vmach := vm.NewVM(txCache, vm.DefaultDynamicMemoryProvider, params,
-		caller.Address, nil)
-	gas := gasLimit
-	ret, err := vmach.Call(caller, callee, code, data, 0, &gas)
-	if err != nil {
-		return nil, err
-	}
-	gasUsed := gasLimit - gas
-	// here return bytes are hex encoded; on the sibling function
-	// they are not
-	return &core_types.Call{Return: hex.EncodeToString(ret), GasUsed: gasUsed}, nil
-}
-
-// Broadcast a transaction.
-func (this *transactor) BroadcastTx(tx txs.Tx) (*txs.Receipt, error) {
-	err := this.txBroadcaster(tx)
-
-	if err != nil {
-		return nil, fmt.Errorf("Error broadcasting transaction: %v", err)
-	}
-
-	txHash := txs.TxHash(this.chainID, tx)
-	var createsContract uint8
-	var contractAddr []byte
-	// check if creates new contract
-	if callTx, ok := tx.(*txs.CallTx); ok {
-		if len(callTx.Address) == 0 {
-			createsContract = 1
-			contractAddr = state.NewContractAddress(callTx.Input.Address, callTx.Input.Sequence)
-		}
-	}
-	return &txs.Receipt{txHash, createsContract, contractAddr}, nil
-}
-
-// Orders calls to BroadcastTx using lock (waits for response from core before releasing)
-func (this *transactor) Transact(privKey, address, data []byte, gasLimit,
-	fee int64) (*txs.Receipt, error) {
-	var addr []byte
-	if len(address) == 0 {
-		addr = nil
-	} else if len(address) != 20 {
-		return nil, fmt.Errorf("Address is not of the right length: %d\n", len(address))
-	} else {
-		addr = address
-	}
-	if len(privKey) != 64 {
-		return nil, fmt.Errorf("Private key is not of the right length: %d\n", len(privKey))
-	}
-	this.txMtx.Lock()
-	defer this.txMtx.Unlock()
-	pa := account.GenPrivAccountFromPrivKeyBytes(privKey)
-	cache := this.burrowMint.GetCheckCache() // XXX: DON'T MUTATE THIS CACHE (used internally for CheckTx)
-	acc := cache.GetAccount(pa.Address)
-	var sequence int
-	if acc == nil {
-		sequence = 1
-	} else {
-		sequence = acc.Sequence + 1
-	}
-	// TODO: [Silas] we should consider revising this method and removing fee, or
-	// possibly adding an amount parameter. It is non-sensical to just be able to
-	// set the fee. Our support of fees in general is questionable since at the
-	// moment all we do is deduct the fee effectively leaking token. It is possible
-	// someone may be using the sending of native token to payable functions but
-	// they can be served by broadcasting a token.
-
-	// We hard-code the amount to be equal to the fee which means the CallTx we
-	// generate transfers 0 value, which is the most sensible default since in
-	// recent solidity compilers the EVM generated will throw an error if value
-	// is transferred to a non-payable function.
-	txInput := &txs.TxInput{
-		Address:  pa.Address,
-		Amount:   fee,
-		Sequence: sequence,
-		PubKey:   pa.PubKey,
-	}
-	tx := &txs.CallTx{
-		Input:    txInput,
-		Address:  addr,
-		GasLimit: gasLimit,
-		Fee:      fee,
-		Data:     data,
-	}
-
-	// Got ourselves a tx.
-	txS, errS := this.SignTx(tx, []*account.PrivAccount{pa})
-	if errS != nil {
-		return nil, errS
-	}
-	return this.BroadcastTx(txS)
-}
-
-func (this *transactor) TransactAndHold(privKey, address, data []byte, gasLimit, fee int64) (*txs.EventDataCall, error) {
-	rec, tErr := this.Transact(privKey, address, data, gasLimit, fee)
-	if tErr != nil {
-		return nil, tErr
-	}
-	var addr []byte
-	if rec.CreatesContract == 1 {
-		addr = rec.ContractAddr
-	} else {
-		addr = address
-	}
-	// We want non-blocking on the first event received (but buffer the value),
-	// after which we want to block (and then discard the value - see below)
-	wc := make(chan *txs.EventDataCall, 1)
-	subId := fmt.Sprintf("%X", rec.TxHash)
-	this.eventEmitter.Subscribe(subId, txs.EventStringAccCall(addr),
-		func(evt txs.EventData) {
-			eventDataCall := evt.(txs.EventDataCall)
-			if bytes.Equal(eventDataCall.TxID, rec.TxHash) {
-				// Beware the contract of go-events subscribe is that we must not be
-				// blocking in an event callback when we try to unsubscribe!
-				// We work around this by using a non-blocking send.
-				select {
-				// This is a non-blocking send, but since we are using a buffered
-				// channel of size 1 we will always grab our first event even if we
-				// haven't read from the channel at the time we receive the first event.
-				case wc <- &eventDataCall:
-				default:
-				}
-			}
-		})
-
-	timer := time.NewTimer(300 * time.Second)
-	toChan := timer.C
-
-	var ret *txs.EventDataCall
-	var rErr error
-
-	select {
-	case <-toChan:
-		rErr = fmt.Errorf("Transaction timed out. Hash: " + subId)
-	case e := <-wc:
-		timer.Stop()
-		if e.Exception != "" {
-			rErr = fmt.Errorf("Error when transacting: " + e.Exception)
-		} else {
-			ret = e
-		}
-	}
-	this.eventEmitter.Unsubscribe(subId)
-	return ret, rErr
-}
-
-func (this *transactor) Send(privKey, toAddress []byte,
-	amount int64) (*txs.Receipt, error) {
-	var toAddr []byte
-	if len(toAddress) == 0 {
-		toAddr = nil
-	} else if len(toAddress) != 20 {
-		return nil, fmt.Errorf("To-address is not of the right length: %d\n",
-			len(toAddress))
-	} else {
-		toAddr = toAddress
-	}
-
-	if len(privKey) != 64 {
-		return nil, fmt.Errorf("Private key is not of the right length: %d\n",
-			len(privKey))
-	}
-
-	pk := &[64]byte{}
-	copy(pk[:], privKey)
-	this.txMtx.Lock()
-	defer this.txMtx.Unlock()
-	pa := account.GenPrivAccountFromPrivKeyBytes(privKey)
-	cache := this.burrowMint.GetState()
-	acc := cache.GetAccount(pa.Address)
-	var sequence int
-	if acc == nil {
-		sequence = 1
-	} else {
-		sequence = acc.Sequence + 1
-	}
-
-	tx := txs.NewSendTx()
-
-	txInput := &txs.TxInput{
-		Address:  pa.Address,
-		Amount:   amount,
-		Sequence: sequence,
-		PubKey:   pa.PubKey,
-	}
-
-	tx.Inputs = append(tx.Inputs, txInput)
-
-	txOutput := &txs.TxOutput{toAddr, amount}
-
-	tx.Outputs = append(tx.Outputs, txOutput)
-
-	// Got ourselves a tx.
-	txS, errS := this.SignTx(tx, []*account.PrivAccount{pa})
-	if errS != nil {
-		return nil, errS
-	}
-	return this.BroadcastTx(txS)
-}
-
-func (this *transactor) SendAndHold(privKey, toAddress []byte,
-	amount int64) (*txs.Receipt, error) {
-	rec, tErr := this.Send(privKey, toAddress, amount)
-	if tErr != nil {
-		return nil, tErr
-	}
-
-	wc := make(chan *txs.SendTx)
-	subId := fmt.Sprintf("%X", rec.TxHash)
-
-	this.eventEmitter.Subscribe(subId, txs.EventStringAccOutput(toAddress),
-		func(evt txs.EventData) {
-			event := evt.(txs.EventDataTx)
-			tx := event.Tx.(*txs.SendTx)
-			wc <- tx
-		})
-
-	timer := time.NewTimer(300 * time.Second)
-	toChan := timer.C
-
-	var rErr error
-
-	pa := account.GenPrivAccountFromPrivKeyBytes(privKey)
-
-	select {
-	case <-toChan:
-		rErr = fmt.Errorf("Transaction timed out. Hash: " + subId)
-	case e := <-wc:
-		if bytes.Equal(e.Inputs[0].Address, pa.Address) && e.Inputs[0].Amount == amount {
-			timer.Stop()
-			this.eventEmitter.Unsubscribe(subId)
-			return rec, rErr
-		}
-	}
-	return nil, rErr
-}
-
-func (this *transactor) TransactNameReg(privKey []byte, name, data string,
-	amount, fee int64) (*txs.Receipt, error) {
-
-	if len(privKey) != 64 {
-		return nil, fmt.Errorf("Private key is not of the right length: %d\n", len(privKey))
-	}
-	this.txMtx.Lock()
-	defer this.txMtx.Unlock()
-	pa := account.GenPrivAccountFromPrivKeyBytes(privKey)
-	cache := this.burrowMint.GetCheckCache() // XXX: DON'T MUTATE THIS CACHE (used internally for CheckTx)
-	acc := cache.GetAccount(pa.Address)
-	var sequence int
-	if acc == nil {
-		sequence = 1
-	} else {
-		sequence = acc.Sequence + 1
-	}
-	tx := txs.NewNameTxWithNonce(pa.PubKey, name, data, amount, fee, sequence)
-	// Got ourselves a tx.
-	txS, errS := this.SignTx(tx, []*account.PrivAccount{pa})
-	if errS != nil {
-		return nil, errS
-	}
-	return this.BroadcastTx(txS)
-}
-
-// Sign a transaction
-func (this *transactor) SignTx(tx txs.Tx, privAccounts []*account.PrivAccount) (txs.Tx, error) {
-	// more checks?
-
-	for i, privAccount := range privAccounts {
-		if privAccount == nil || privAccount.PrivKey == nil {
-			return nil, fmt.Errorf("Invalid (empty) privAccount @%v", i)
-		}
-	}
-	switch tx.(type) {
-	case *txs.NameTx:
-		nameTx := tx.(*txs.NameTx)
-		nameTx.Input.PubKey = privAccounts[0].PubKey
-		nameTx.Input.Signature = privAccounts[0].Sign(this.chainID, nameTx)
-	case *txs.SendTx:
-		sendTx := tx.(*txs.SendTx)
-		for i, input := range sendTx.Inputs {
-			input.PubKey = privAccounts[i].PubKey
-			input.Signature = privAccounts[i].Sign(this.chainID, sendTx)
-		}
-	case *txs.CallTx:
-		callTx := tx.(*txs.CallTx)
-		callTx.Input.PubKey = privAccounts[0].PubKey
-		callTx.Input.Signature = privAccounts[0].Sign(this.chainID, callTx)
-	case *txs.BondTx:
-		bondTx := tx.(*txs.BondTx)
-		// the first privaccount corresponds to the BondTx pub key.
-		// the rest to the inputs
-		bondTx.Signature = privAccounts[0].Sign(this.chainID, bondTx).(crypto.SignatureEd25519)
-		for i, input := range bondTx.Inputs {
-			input.PubKey = privAccounts[i+1].PubKey
-			input.Signature = privAccounts[i+1].Sign(this.chainID, bondTx)
-		}
-	case *txs.UnbondTx:
-		unbondTx := tx.(*txs.UnbondTx)
-		unbondTx.Signature = privAccounts[0].Sign(this.chainID, unbondTx).(crypto.SignatureEd25519)
-	case *txs.RebondTx:
-		rebondTx := tx.(*txs.RebondTx)
-		rebondTx.Signature = privAccounts[0].Sign(this.chainID, rebondTx).(crypto.SignatureEd25519)
-	default:
-		return nil, fmt.Errorf("Object is not a proper transaction: %v\n", tx)
-	}
-	return tx, nil
-}
-
-// No idea what this does.
-func toVMAccount(acc *account.Account) *vm.Account {
-	return &vm.Account{
-		Address: word256.LeftPadWord256(acc.Address),
-		Balance: acc.Balance,
-		Code:    acc.Code,
-		Nonce:   int64(acc.Sequence),
-		Other:   acc.PubKey,
-	}
-}
diff --git a/manager/burrow-mint/version.go b/manager/burrow-mint/version.go
deleted file mode 100644
index 888de79c..00000000
--- a/manager/burrow-mint/version.go
+++ /dev/null
@@ -1,53 +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 burrowmint
-
-import (
-	"fmt"
-
-	version "github.com/hyperledger/burrow/version"
-)
-
-const (
-	// Client identifier to advertise over the network
-	burrowMintClientIdentifier = "burrowmint"
-	// Major version component of the current release
-	burrowMintVersionMajor = 0
-	// Minor version component of the current release
-	burrowMintVersionMinor = 17
-	// Patch version component of the current release
-	burrowMintVersionPatch = 0
-)
-
-// Define the compatible consensus engines this application manager
-// is compatible and has been tested with.
-var compatibleConsensus = [...]string{
-	"tendermint-0.9",
-}
-
-func GetBurrowMintVersion() *version.VersionIdentifier {
-	return version.New(burrowMintClientIdentifier, burrowMintVersionMajor,
-		burrowMintVersionMinor, burrowMintVersionPatch)
-}
-
-func AssertCompatibleConsensus(consensusMinorVersion string) error {
-	for _, supported := range compatibleConsensus {
-		if consensusMinorVersion == supported {
-			return nil
-		}
-	}
-	return fmt.Errorf("BurrowMint (%s) is not compatible with consensus engine %s",
-		GetBurrowMintVersion(), consensusMinorVersion)
-}
diff --git a/manager/manager.go b/manager/manager.go
deleted file mode 100644
index 2724b126..00000000
--- a/manager/manager.go
+++ /dev/null
@@ -1,44 +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 manager
-
-import (
-	"fmt"
-
-	events "github.com/tendermint/go-events"
-
-	config "github.com/hyperledger/burrow/config"
-	definitions "github.com/hyperledger/burrow/definitions"
-	burrowmint "github.com/hyperledger/burrow/manager/burrow-mint"
-
-	"github.com/hyperledger/burrow/logging"
-	logging_types "github.com/hyperledger/burrow/logging/types"
-)
-
-// NewApplicationPipe returns an initialised Pipe interface
-// based on the loaded module configuration file.
-// NOTE: [ben] Currently we only have a single `generic` definition
-// of an application.  It is feasible this will be insufficient to support
-// different types of applications later down the line.
-func NewApplicationPipe(moduleConfig *config.ModuleConfig,
-	evsw events.EventSwitch,
-	logger logging_types.InfoTraceLogger) (definitions.Pipe, error) {
-	switch moduleConfig.Name {
-	case "burrowmint":
-		logging.InfoMsg(logger, "Loading BurrowMint")
-		return burrowmint.NewBurrowMintPipe(moduleConfig, evsw, logger)
-	}
-	return nil, fmt.Errorf("Failed to return Pipe for %s", moduleConfig.Name)
-}
diff --git a/manager/types/application.go b/manager/types/application.go
deleted file mode 100644
index 2025742b..00000000
--- a/manager/types/application.go
+++ /dev/null
@@ -1,104 +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 types
-
-import (
-	// TODO: [ben] this is currently only used for abci result type; but should
-	// be removed as abci dependencies shouldn't feature in the application
-	// manager
-	consensus_types "github.com/hyperledger/burrow/consensus/types"
-	abci "github.com/tendermint/abci/types"
-)
-
-// NOTE: [ben] this interface is likely to be changed.  Currently it is taken
-// from the tendermint socket protocol application interface;
-
-// Application interface applies transactions to the state.
-type Application interface {
-
-	// Info returns application information as a string
-	// NOTE: [ben] likely to move
-	Info() (info abci.ResponseInfo)
-
-	// Set application option (e.g. mode=mempool, mode=consensus)
-	// NOTE: [ben] taken from tendermint, but it is unclear what the use is,
-	// specifically, when will tendermint call this over abci ?
-	SetOption(key string, value string) (log string)
-
-	// Append transaction applies a transaction to the state regardless of
-	// whether the transaction is valid or not.
-	// Currently AppendTx is taken from abci, and returns a result.
-	// This will be altered, as AppendTransaction needs to more strongly reflect
-	// the theoretical logic:
-	//   Append(StateN, Transaction) = StateN+1
-	// here invalid transactions are allowed, but should act as the identity on
-	// the state:
-	//   Append(StateN, InvalidTransaction) = StateN
-	// TODO: implementation notes:
-	// 1. at this point the transaction should already be strongly typed
-	// 2.
-	DeliverTx(tx []byte) abci.Result
-
-	// Check Transaction validates a transaction before being allowed into the
-	// consensus' engine memory pool.  This is the original defintion and
-	// intention as taken from abci, but should be remapped to the more
-	// general concept of basic, cheap verification;
-	// Check Transaction does not alter the state, but does require an immutable
-	// copy of the state. In particular there is no consensus on ordering yet.
-	// TODO: implementation notes:
-	// 1. at this point the transaction should already be strongly typed
-	// 2.
-	CheckTx(tx []byte) abci.Result
-
-	// Commit returns the root hash of the current application state
-	// NOTE: [ben] Because the concept of the block has been erased here
-	// the commit root hash is a fully implict stateful function;
-	// the opposit the principle of explicit stateless functions.
-	// This will be amended when we introduce the concept of (streaming)
-	// blocks in the pipe.
-	Commit() abci.Result
-
-	// Query for state.  This query request is not passed over the p2p network
-	// and is called from Tenderpmint rpc directly up to the application.
-	// NOTE: [ben] burrow will give preference to queries from the local client
-	// directly over the burrow rpc.
-	// We will support this for Tendermint compatibility.
-	Query(reqQuery abci.RequestQuery) abci.ResponseQuery
-
-	// Tendermint acbi_types.Application extends our base definition of an
-	// Application with a parenthetical (begin/end) streaming block interface
-
-	// Initialise the blockchain
-	// When Tendermint initialises the genesis validators from tendermint core
-	// are passed in as validators
-	InitChain(validators []*abci.Validator)
-
-	// Signals the beginning of communicating a block (all transactions have been
-	// closed into the block already
-	BeginBlock(hash []byte, header *abci.Header)
-
-	// Signals the end of a blockchain
-	// ResponseEndBlock wraps a slice of Validators with the Diff field. A Validator
-	// is a public key and a voting power. Returning a Validator within this slice
-	// asks Tendermint to set that validator's voting power to the Power provided.
-	// Note: although the field is named 'Diff' the intention is that it declares
-	// the what the new voting power should be (for validators specified,
-	// those omitted are left alone) it is not an relative increment to
-	// be added (or subtracted) from voting power.
-	EndBlock(height uint64) abci.ResponseEndBlock
-
-	// Is this the passed ConsensusEngine compatible with this manager
-	CompatibleConsensus(consensusEngine consensus_types.ConsensusEngine) bool
-}
diff --git a/rpc/v0/rest_server_pipe_test.go b/rpc/v0/rest_server_pipe_test.go
deleted file mode 100644
index 1cd82822..00000000
--- a/rpc/v0/rest_server_pipe_test.go
+++ /dev/null
@@ -1,313 +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 v0
-
-import (
-	"fmt"
-
-	account "github.com/hyperledger/burrow/account"
-	core_types "github.com/hyperledger/burrow/core/types"
-	definitions "github.com/hyperledger/burrow/definitions"
-	event "github.com/hyperledger/burrow/event"
-
-	blockchain_types "github.com/hyperledger/burrow/blockchain/types"
-	consensus_types "github.com/hyperledger/burrow/consensus/types"
-	logging_types "github.com/hyperledger/burrow/logging/types"
-	manager_types "github.com/hyperledger/burrow/manager/types"
-	"github.com/hyperledger/burrow/txs"
-
-	"github.com/hyperledger/burrow/logging/loggers"
-	abci_types "github.com/tendermint/abci/types"
-	"github.com/tendermint/go-crypto"
-	"github.com/tendermint/go-p2p"
-	mintTypes "github.com/tendermint/tendermint/types"
-)
-
-// Base struct.
-type MockPipe struct {
-	testData        TestData
-	accounts        definitions.Accounts
-	blockchain      blockchain_types.Blockchain
-	consensusEngine consensus_types.ConsensusEngine
-	events          event.EventEmitter
-	namereg         definitions.NameReg
-	transactor      definitions.Transactor
-	logger          logging_types.InfoTraceLogger
-}
-
-// Create a new mock tendermint pipe.
-func NewMockPipe(td *TestData) definitions.Pipe {
-	return &MockPipe{
-		testData:        *td,
-		accounts:        &accounts{td},
-		blockchain:      &chain{td},
-		consensusEngine: &consensusEngine{td},
-		events:          &eventer{td},
-		namereg:         &namereg{td},
-		transactor:      &transactor{td},
-		logger:          loggers.NewNoopInfoTraceLogger(),
-	}
-}
-
-// Create a mock pipe with default mock data.
-func NewDefaultMockPipe() definitions.Pipe {
-	return NewMockPipe(LoadTestData())
-}
-
-func (pipe *MockPipe) Accounts() definitions.Accounts {
-	return pipe.accounts
-}
-
-func (pipe *MockPipe) Blockchain() blockchain_types.Blockchain {
-	return pipe.blockchain
-}
-
-func (pipe *MockPipe) Events() event.EventEmitter {
-	return pipe.events
-}
-
-func (pipe *MockPipe) NameReg() definitions.NameReg {
-	return pipe.namereg
-}
-
-func (pipe *MockPipe) Transactor() definitions.Transactor {
-	return pipe.transactor
-}
-
-func (pipe *MockPipe) Logger() logging_types.InfoTraceLogger {
-	return pipe.logger
-}
-
-func (pipe *MockPipe) GetApplication() manager_types.Application {
-	// TODO: [ben] mock application
-	return nil
-}
-
-func (pipe *MockPipe) SetConsensusEngine(_ consensus_types.ConsensusEngine) error {
-	// TODO: [ben] mock consensus engine
-	return nil
-}
-
-func (pipe *MockPipe) GetConsensusEngine() consensus_types.ConsensusEngine {
-	return pipe.consensusEngine
-}
-
-func (pipe *MockPipe) SetBlockchain(_ blockchain_types.Blockchain) error {
-	// TODO: [ben] mock consensus engine
-	return nil
-}
-
-func (pipe *MockPipe) GetBlockchain() blockchain_types.Blockchain {
-	return nil
-}
-
-func (pipe *MockPipe) GetTendermintPipe() (definitions.TendermintPipe, error) {
-	return nil, fmt.Errorf("Tendermint pipe is not supported by mocked pipe.")
-}
-
-func (pipe *MockPipe) GenesisHash() []byte {
-	return pipe.testData.GetGenesisHash.Output.Hash
-}
-
-// Components
-
-// Accounts
-type accounts struct {
-	testData *TestData
-}
-
-func (acc *accounts) GenPrivAccount() (*account.PrivAccount, error) {
-	return acc.testData.GenPrivAccount.Output, nil
-}
-
-func (acc *accounts) GenPrivAccountFromKey(key []byte) (*account.PrivAccount, error) {
-	return acc.testData.GenPrivAccount.Output, nil
-}
-
-func (acc *accounts) Accounts([]*event.FilterData) (*core_types.AccountList, error) {
-	return acc.testData.GetAccounts.Output, nil
-}
-
-func (acc *accounts) Account(address []byte) (*account.Account, error) {
-	return acc.testData.GetAccount.Output, nil
-}
-
-func (acc *accounts) Storage(address []byte) (*core_types.Storage, error) {
-	return acc.testData.GetStorage.Output, nil
-}
-
-func (acc *accounts) StorageAt(address, key []byte) (*core_types.StorageItem, error) {
-	return acc.testData.GetStorageAt.Output, nil
-}
-
-// Blockchain
-type chain struct {
-	testData *TestData
-}
-
-func (this *chain) ChainId() string {
-	return this.testData.GetChainId.Output.ChainId
-}
-
-func (this *chain) Height() int {
-	return this.testData.GetLatestBlockHeight.Output.Height
-}
-
-func (this *chain) Block(height int) *mintTypes.Block {
-	return this.testData.GetBlock.Output
-}
-
-func (this *chain) BlockMeta(height int) *mintTypes.BlockMeta {
-	return &mintTypes.BlockMeta{}
-}
-
-// Consensus
-type consensusEngine struct {
-	testData *TestData
-}
-
-func (cons *consensusEngine) BroadcastTransaction(transaction []byte,
-	callback func(*abci_types.Response)) error {
-	return nil
-}
-
-func (cons *consensusEngine) IsListening() bool {
-	return cons.testData.IsListening.Output.Listening
-}
-
-func (cons *consensusEngine) Listeners() []p2p.Listener {
-	p2pListeners := make([]p2p.Listener, 0)
-
-	for _, name := range cons.testData.GetListeners.Output.Listeners {
-		p2pListeners = append(p2pListeners, p2p.NewDefaultListener("tcp", name, true))
-	}
-
-	return p2pListeners
-}
-
-func (cons *consensusEngine) NodeInfo() *p2p.NodeInfo {
-	return &p2p.NodeInfo{
-		Version: cons.testData.GetNetworkInfo.Output.ClientVersion,
-		Moniker: cons.testData.GetNetworkInfo.Output.Moniker,
-	}
-}
-
-func (cons *consensusEngine) Peers() []*consensus_types.Peer {
-	return cons.testData.GetPeers.Output
-}
-
-func (cons *consensusEngine) PublicValidatorKey() crypto.PubKey {
-	return crypto.PubKeyEd25519{
-		1, 2, 3, 4, 5, 6, 7, 8,
-		1, 2, 3, 4, 5, 6, 7, 8,
-		1, 2, 3, 4, 5, 6, 7, 8,
-		1, 2, 3, 4, 5, 6, 7, 8,
-	}
-}
-
-func (cons *consensusEngine) Events() event.EventEmitter {
-	return nil
-}
-
-func (cons *consensusEngine) ListUnconfirmedTxs(maxTxs int) ([]txs.Tx, error) {
-	return cons.testData.GetUnconfirmedTxs.Output.Txs, nil
-}
-
-func (cons *consensusEngine) ListValidators() []consensus_types.Validator {
-	return nil
-}
-
-func (cons *consensusEngine) ConsensusState() *consensus_types.ConsensusState {
-	return &consensus_types.ConsensusState{}
-}
-
-func (cons *consensusEngine) PeerConsensusStates() map[string]string {
-	return map[string]string{}
-}
-
-func (cons *consensusEngine) Stop() bool {
-	return true
-}
-
-// Events
-type eventer struct {
-	testData *TestData
-}
-
-func (evntr *eventer) Subscribe(subId, event string, callback func(txs.EventData)) error {
-	return nil
-}
-
-func (evntr *eventer) Unsubscribe(subId string) error {
-	return nil
-}
-
-// NameReg
-type namereg struct {
-	testData *TestData
-}
-
-func (nmreg *namereg) Entry(key string) (*core_types.NameRegEntry, error) {
-	return nmreg.testData.GetNameRegEntry.Output, nil
-}
-
-func (nmreg *namereg) Entries(filters []*event.FilterData) (*core_types.ResultListNames, error) {
-	return nmreg.testData.GetNameRegEntries.Output, nil
-}
-
-// Txs
-type transactor struct {
-	testData *TestData
-}
-
-func (trans *transactor) Call(fromAddress, toAddress, data []byte) (*core_types.Call, error) {
-	return trans.testData.Call.Output, nil
-}
-
-func (trans *transactor) CallCode(from, code, data []byte) (*core_types.Call, error) {
-	return trans.testData.CallCode.Output, nil
-}
-
-func (trans *transactor) BroadcastTx(tx txs.Tx) (*txs.Receipt, error) {
-	receipt := txs.GenerateReceipt(trans.testData.GetChainId.Output.ChainId, tx)
-	return &receipt, nil
-}
-
-func (trans *transactor) Transact(privKey, address, data []byte, gasLimit, fee int64) (*txs.Receipt, error) {
-	if len(address) == 0 {
-		return trans.testData.TransactCreate.Output, nil
-	}
-	return trans.testData.Transact.Output, nil
-}
-
-func (trans *transactor) TransactAndHold(privKey, address, data []byte, gasLimit, fee int64) (*txs.EventDataCall, error) {
-	return nil, nil
-}
-
-func (trans *transactor) Send(privKey, toAddress []byte, amount int64) (*txs.Receipt, error) {
-	return nil, nil
-}
-
-func (trans *transactor) SendAndHold(privKey, toAddress []byte, amount int64) (*txs.Receipt, error) {
-	return nil, nil
-}
-
-func (trans *transactor) TransactNameReg(privKey []byte, name, data string, amount, fee int64) (*txs.Receipt, error) {
-	return trans.testData.TransactNameReg.Output, nil
-}
-
-func (trans *transactor) SignTx(tx txs.Tx, privAccounts []*account.PrivAccount) (txs.Tx, error) {
-	return nil, nil
-}
diff --git a/util/snatives/cmd/main.go b/util/snatives/cmd/main.go
index 16711bd0..a20bbe71 100644
--- a/util/snatives/cmd/main.go
+++ b/util/snatives/cmd/main.go
@@ -17,13 +17,13 @@ package main
 import (
 	"fmt"
 
-	"github.com/hyperledger/burrow/manager/burrow-mint/evm"
+	"github.com/hyperledger/burrow/execution/evm"
 	"github.com/hyperledger/burrow/util/snatives/templates"
 )
 
 // Dump SNative contracts
 func main() {
-	contracts := vm.SNativeContracts()
+	contracts := evm.SNativeContracts()
 	// Index of next contract
 	i := 1
 	fmt.Print("pragma solidity >=0.0.0;\n\n")
diff --git a/util/snatives/templates/solidity_templates.go b/util/snatives/templates/solidity_templates.go
index 165a2e6a..fec8861a 100644
--- a/util/snatives/templates/solidity_templates.go
+++ b/util/snatives/templates/solidity_templates.go
@@ -20,7 +20,7 @@ import (
 	"strings"
 	"text/template"
 
-	"github.com/hyperledger/burrow/manager/burrow-mint/evm"
+	"github.com/hyperledger/burrow/execution/evm"
 )
 
 const contractTemplateText = `/**
@@ -63,11 +63,11 @@ func init() {
 }
 
 type solidityContract struct {
-	*vm.SNativeContractDescription
+	*evm.SNativeContractDescription
 }
 
 type solidityFunction struct {
-	*vm.SNativeFunctionDescription
+	*evm.SNativeFunctionDescription
 }
 
 //
@@ -75,7 +75,7 @@ type solidityFunction struct {
 //
 
 // Create a templated solidityContract from an SNative contract description
-func NewSolidityContract(contract *vm.SNativeContractDescription) *solidityContract {
+func NewSolidityContract(contract *evm.SNativeContractDescription) *solidityContract {
 	return &solidityContract{contract}
 }
 
@@ -95,7 +95,7 @@ func (contract *solidityContract) InstanceName() string {
 }
 
 func (contract *solidityContract) Address() string {
-	return fmt.Sprintf("0x%x",
+	return fmt.Sprintf("0x%s",
 		contract.SNativeContractDescription.Address())
 }
 
@@ -123,7 +123,7 @@ func (contract *solidityContract) Functions() []*solidityFunction {
 //
 
 // Create a templated solidityFunction from an SNative function description
-func NewSolidityFunction(function *vm.SNativeFunctionDescription) *solidityFunction {
+func NewSolidityFunction(function *evm.SNativeFunctionDescription) *solidityFunction {
 	return &solidityFunction{function}
 }
 
diff --git a/util/snatives/templates/solidity_templates_test.go b/util/snatives/templates/solidity_templates_test.go
index 58fe37f7..998aa11f 100644
--- a/util/snatives/templates/solidity_templates_test.go
+++ b/util/snatives/templates/solidity_templates_test.go
@@ -18,12 +18,12 @@ import (
 	"fmt"
 	"testing"
 
-	"github.com/hyperledger/burrow/manager/burrow-mint/evm"
+	"github.com/hyperledger/burrow/execution/evm"
 	"github.com/stretchr/testify/assert"
 )
 
 func TestSNativeFuncTemplate(t *testing.T) {
-	contract := vm.SNativeContracts()["Permissions"]
+	contract := evm.SNativeContracts()["Permissions"]
 	function, err := contract.FunctionByName("removeRole")
 	if err != nil {
 		t.Fatal("Couldn't get function")
@@ -37,7 +37,7 @@ func TestSNativeFuncTemplate(t *testing.T) {
 // This test checks that we can generate the SNative contract interface and
 // prints it to stdout
 func TestSNativeContractTemplate(t *testing.T) {
-	contract := vm.SNativeContracts()["Permissions"]
+	contract := evm.SNativeContracts()["Permissions"]
 	solidityContract := NewSolidityContract(contract)
 	solidity, err := solidityContract.Solidity()
 	assert.NoError(t, err)
-- 
GitLab