From eb0c993d24867089a7cd6a682afb5f38f9e96d16 Mon Sep 17 00:00:00 2001
From: Silas Davis <silas@monax.io>
Date: Sun, 22 Jul 2018 14:18:54 +0100
Subject: [PATCH] GovTx based validator set changes implemented and tested

Signed-off-by: Silas Davis <silas@monax.io>
---
 Gopkg.lock                                    |   3 +-
 acm/balance/balance.go                        | 118 ++++
 acm/balance/balance.pb.go                     | 337 ++++++++++
 acm/balance/balance_test.go                   |  22 +
 acm/balance/type.go                           |  51 ++
 acm/validator.go                              |  92 ---
 acm/validator/ring.go                         | 265 ++++++++
 .../validator/ring_test.go                    |  26 +-
 .../validators.go => acm/validator/set.go     | 126 ++--
 .../validator/set_test.go                     |   8 +-
 acm/validator/validator.go                    |  27 +
 acm/validator/validator.pb.go                 | 405 ++++++++++++
 acm/validator/validators.go                   | 111 ++++
 acm/validator_test.go                         |   1 -
 {blockchain => bcm}/blockchain.go             | 195 +++---
 {blockchain => bcm}/blockchain_test.go        |  23 +-
 blockchain/validators_ring.go                 | 198 ------
 cmd/burrow/commands/configure.go              |   4 +-
 cmd/burrow/commands/helpers.go                |   2 +-
 cmd/burrow/commands/tx.go                     |   1 +
 config/config.go                              |  12 +-
 consensus/tendermint/abci/app.go              |  90 +--
 consensus/tendermint/config.go                |   7 +-
 consensus/tendermint/{query => }/node_view.go |  12 +-
 .../{validator => }/priv_validator_memory.go  |   2 +-
 .../tendermint/{validator => }/sign_info.go   |   2 +-
 consensus/tendermint/tendermint.go            |   8 +-
 consensus/tendermint/{validator => }/wire.go  |   2 +-
 core/kernel.go                                |  98 +--
 crypto/public_key.go                          |  12 +
 execution/contexts/call_context.go            |   6 +-
 execution/contexts/governance_context.go      |  36 +-
 execution/contexts/name_context.go            |   4 +-
 execution/contexts/permissions_context.go     |  16 +-
 execution/contexts/send_context.go            |   9 +-
 execution/contexts/shared.go                  |  63 +-
 execution/errors/errors.go                    |  11 +-
 execution/errors/errors_test.go               |   2 -
 execution/errors/vm.go                        |   5 +-
 execution/evm/vm.go                           |  20 +-
 execution/exec/exec.pb.go                     | 128 ++--
 execution/execution.go                        |  55 +-
 execution/execution_test.go                   |  28 +-
 execution/simulated_call.go                   |   8 +-
 execution/transactor.go                       |  13 +-
 execution/transactor_test.go                  |   7 +-
 genesis/deterministic_genesis.go              |   8 +-
 genesis/genesis.go                            |  30 +-
 genesis/genesis_test.go                       |   8 +-
 genesis/spec/genesis_spec.go                  |   8 +-
 genesis/spec/genesis_spec_test.go             |   5 +-
 genesis/spec/presets.go                       |  20 +-
 genesis/spec/presets_test.go                  |  11 +-
 genesis/spec/spec.pb.go                       | 166 +++--
 genesis/spec/template_account.go              |  17 +-
 governance/governance.go                      |  38 ++
 governance/governance_test.go                 |  23 +
 integration/core/kernel_test.go               |  65 +-
 integration/governance/governance_test.go     | 172 +++++
 integration/governance/main_test.go           |  55 +-
 integration/governance/validators_test.go     |   7 -
 integration/integration.go                    |  71 +--
 integration/integration_test.go               |  28 +
 integration/rpcevents/main_test.go            |   4 +-
 integration/rpcquery/main_test.go             |   4 +-
 integration/rpctransact/main_test.go          |   4 +-
 .../rpctransact/transact_server_test.go       |   2 +-
 integration/tm/main_test.go                   |   4 +-
 logging/config/presets/instructions_test.go   |  51 --
 logging/config/sort.go                        |   1 -
 logging/lifecycle/lifecycle.go                |   8 +-
 logging/{config => logconfig}/config.go       |  16 +-
 logging/{config => logconfig}/config_test.go  |   2 +-
 logging/{config => logconfig}/filter.go       |   2 +-
 logging/{config => logconfig}/filter_test.go  |   2 +-
 .../presets/instructions.go                   |  64 +-
 .../logconfig/presets/instructions_test.go    |  51 ++
 logging/{config => logconfig}/sinks.go        |  13 +-
 logging/{config => logconfig}/sinks_test.go   |   2 +-
 logging/logconfig/sort.go                     |   1 +
 logging/loggers/burrow_format_logger.go       |   3 +-
 permission/account_permissions.go             |  13 +
 permission/util.go                            |  23 +-
 permission/util_test.go                       |  10 +-
 protobuf/acm.proto                            |   7 +-
 protobuf/balance.proto                        |  20 +
 protobuf/exec.proto                           |   2 +-
 protobuf/payload.proto                        |  12 +-
 protobuf/rpcquery.proto                       |  15 +
 protobuf/rpctransact.proto                    |  10 +-
 protobuf/spec.proto                           |  25 +-
 protobuf/validator.proto                      |  22 +
 rpc/result.go                                 |   8 +-
 rpc/rpcevents/execution_events_server.go      |   6 +-
 rpc/rpcquery/query_server.go                  |  39 +-
 rpc/rpcquery/rpcquery.pb.go                   | 603 +++++++++++++++++-
 rpc/rpctransact/rpctransact.pb.go             | 355 ++---------
 rpc/rpctransact/transact_server.go            |  60 +-
 rpc/service.go                                |  39 +-
 txs/amino_codec.go                            |   4 +-
 txs/payload/bond_tx.go                        |   6 +
 txs/payload/call_tx.go                        |   6 +
 txs/payload/gov_tx.go                         |  23 +
 txs/payload/governance_tx.go                  |  17 -
 txs/payload/name_tx.go                        |   6 +
 txs/payload/payload.go                        |  50 +-
 txs/payload/payload.pb.go                     | 391 ++++++++----
 txs/payload/{permission_tx.go => perms_tx.go} |  22 +-
 txs/payload/send_tx.go                        |   6 +
 txs/payload/unbond_tx.go                      |   6 +
 txs/tx.go                                     |   2 +-
 txs/tx_test.go                                |   4 +-
 util/logging/cmd/main.go                      |   2 +-
 113 files changed, 3711 insertions(+), 1740 deletions(-)
 create mode 100644 acm/balance/balance.go
 create mode 100644 acm/balance/balance.pb.go
 create mode 100644 acm/balance/balance_test.go
 create mode 100644 acm/balance/type.go
 delete mode 100644 acm/validator.go
 create mode 100644 acm/validator/ring.go
 rename blockchain/validators_ring_test.go => acm/validator/ring_test.go (86%)
 rename blockchain/validators.go => acm/validator/set.go (51%)
 rename blockchain/validators_test.go => acm/validator/set_test.go (81%)
 create mode 100644 acm/validator/validator.go
 create mode 100644 acm/validator/validator.pb.go
 create mode 100644 acm/validator/validators.go
 delete mode 100644 acm/validator_test.go
 rename {blockchain => bcm}/blockchain.go (53%)
 rename {blockchain => bcm}/blockchain_test.go (60%)
 delete mode 100644 blockchain/validators_ring.go
 create mode 100644 cmd/burrow/commands/tx.go
 rename consensus/tendermint/{query => }/node_view.go (86%)
 rename consensus/tendermint/{validator => }/priv_validator_memory.go (98%)
 rename consensus/tendermint/{validator => }/sign_info.go (99%)
 rename consensus/tendermint/{validator => }/wire.go (89%)
 create mode 100644 governance/governance_test.go
 create mode 100644 integration/governance/governance_test.go
 delete mode 100644 integration/governance/validators_test.go
 create mode 100644 integration/integration_test.go
 delete mode 100644 logging/config/presets/instructions_test.go
 delete mode 100644 logging/config/sort.go
 rename logging/{config => logconfig}/config.go (84%)
 rename logging/{config => logconfig}/config_test.go (97%)
 rename logging/{config => logconfig}/filter.go (99%)
 rename logging/{config => logconfig}/filter_test.go (99%)
 rename logging/{config => logconfig}/presets/instructions.go (66%)
 create mode 100644 logging/logconfig/presets/instructions_test.go
 rename logging/{config => logconfig}/sinks.go (97%)
 rename logging/{config => logconfig}/sinks_test.go (99%)
 create mode 100644 logging/logconfig/sort.go
 create mode 100644 protobuf/balance.proto
 create mode 100644 protobuf/validator.proto
 create mode 100644 txs/payload/gov_tx.go
 delete mode 100644 txs/payload/governance_tx.go
 rename txs/payload/{permission_tx.go => perms_tx.go} (53%)

diff --git a/Gopkg.lock b/Gopkg.lock
index 6eb70eac..ac4f2f28 100644
--- a/Gopkg.lock
+++ b/Gopkg.lock
@@ -572,14 +572,15 @@
     "github.com/tendermint/tendermint/consensus",
     "github.com/tendermint/tendermint/consensus/types",
     "github.com/tendermint/tendermint/crypto",
+    "github.com/tendermint/tendermint/crypto/tmhash",
     "github.com/tendermint/tendermint/libs/common",
     "github.com/tendermint/tendermint/libs/db",
     "github.com/tendermint/tendermint/libs/log",
     "github.com/tendermint/tendermint/libs/pubsub",
-    "github.com/tendermint/tendermint/mempool",
     "github.com/tendermint/tendermint/node",
     "github.com/tendermint/tendermint/p2p",
     "github.com/tendermint/tendermint/proxy",
+    "github.com/tendermint/tendermint/rpc/core",
     "github.com/tendermint/tendermint/rpc/core/types",
     "github.com/tendermint/tendermint/state",
     "github.com/tendermint/tendermint/types",
diff --git a/acm/balance/balance.go b/acm/balance/balance.go
new file mode 100644
index 00000000..20b5cc85
--- /dev/null
+++ b/acm/balance/balance.go
@@ -0,0 +1,118 @@
+package balance
+
+import "fmt"
+
+type Balances []Balance
+
+func (b Balance) String() string {
+	return fmt.Sprintf("{%v: %d}", b.Type, b.Amount)
+}
+
+func New() Balances {
+	return []Balance{}
+}
+
+func (bs Balances) Len() int {
+	return len(bs)
+}
+
+func (bs Balances) Less(i, j int) bool {
+	if bs[i].Type < bs[j].Type {
+		return true
+	}
+	return bs[i].Type == bs[j].Type && bs[i].Amount < bs[j].Amount
+}
+
+func (bs Balances) Swap(i, j int) {
+	bs[i], bs[j] = bs[j], bs[i]
+}
+
+func (bs Balances) Add(ty Type, amount uint64) Balances {
+	return append(bs, Balance{
+		Type:   ty,
+		Amount: amount,
+	})
+}
+
+func (bs Balances) Native(amount uint64) Balances {
+	return bs.Add(TypeNative, amount)
+}
+
+func (bs Balances) Power(amount uint64) Balances {
+	return bs.Add(TypePower, amount)
+}
+
+func (bs Balances) Sum(bss ...Balances) Balances {
+	return Sum(append(bss, bs)...)
+}
+
+func Sum(bss ...Balances) Balances {
+	sum := New()
+	sumMap := make(map[Type]uint64)
+	for _, bs := range bss {
+		for _, b := range bs {
+			sumMap[b.Type] += b.Amount
+		}
+	}
+	for k, v := range sumMap {
+		sum = sum.Add(k, v)
+	}
+	return sum
+}
+
+func Native(native uint64) Balance {
+	return Balance{
+		Type:   TypeNative,
+		Amount: native,
+	}
+}
+
+func Power(power uint64) Balance {
+	return Balance{
+		Type:   TypePower,
+		Amount: power,
+	}
+}
+
+func (bs Balances) Has(ty Type) bool {
+	for _, b := range bs {
+		if b.Type == ty {
+			return true
+		}
+	}
+	return false
+}
+
+func (bs Balances) Get(ty Type) *uint64 {
+	for _, b := range bs {
+		if b.Type == ty {
+			return &b.Amount
+		}
+	}
+	return nil
+}
+
+func (bs Balances) GetFallback(ty Type, fallback uint64) uint64 {
+	for _, b := range bs {
+		if b.Type == ty {
+			return b.Amount
+		}
+	}
+	return fallback
+}
+
+func (bs Balances) GetNative(fallback uint64) uint64 {
+	return bs.GetFallback(TypeNative, fallback)
+}
+
+func (bs Balances) GetPower(fallback uint64) uint64 {
+	return bs.GetFallback(TypePower, fallback)
+}
+
+func (bs Balances) HasNative() bool {
+	return bs.Has(TypeNative)
+}
+
+func (bs Balances) HasPower() bool {
+	return bs.Has(TypePower)
+}
diff --git a/acm/balance/balance.pb.go b/acm/balance/balance.pb.go
new file mode 100644
index 00000000..c1e0bdbd
--- /dev/null
+++ b/acm/balance/balance.pb.go
@@ -0,0 +1,337 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: balance.proto
+
+/*
+	Package balance is a generated protocol buffer package.
+
+	It is generated from these files:
+		balance.proto
+
+	It has these top-level messages:
+		Balance
+*/
+package balance
+
+import proto "github.com/gogo/protobuf/proto"
+import golang_proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+import _ "github.com/gogo/protobuf/gogoproto"
+
+import io "io"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = golang_proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
+
+type Balance struct {
+	Type   Type   `protobuf:"varint,1,opt,name=Type,proto3,casttype=Type" json:"Type,omitempty"`
+	Amount uint64 `protobuf:"varint,2,opt,name=Amount,proto3" json:"Amount,omitempty"`
+}
+
+func (m *Balance) Reset()                    { *m = Balance{} }
+func (*Balance) ProtoMessage()               {}
+func (*Balance) Descriptor() ([]byte, []int) { return fileDescriptorBalance, []int{0} }
+
+func (m *Balance) GetType() Type {
+	if m != nil {
+		return m.Type
+	}
+	return 0
+}
+
+func (m *Balance) GetAmount() uint64 {
+	if m != nil {
+		return m.Amount
+	}
+	return 0
+}
+
+func (*Balance) XXX_MessageName() string {
+	return "balance.Balance"
+}
+func init() {
+	proto.RegisterType((*Balance)(nil), "balance.Balance")
+	golang_proto.RegisterType((*Balance)(nil), "balance.Balance")
+}
+func (m *Balance) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalTo(dAtA)
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Balance) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if m.Type != 0 {
+		dAtA[i] = 0x8
+		i++
+		i = encodeVarintBalance(dAtA, i, uint64(m.Type))
+	}
+	if m.Amount != 0 {
+		dAtA[i] = 0x10
+		i++
+		i = encodeVarintBalance(dAtA, i, uint64(m.Amount))
+	}
+	return i, nil
+}
+
+func encodeVarintBalance(dAtA []byte, offset int, v uint64) int {
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return offset + 1
+}
+func (m *Balance) Size() (n int) {
+	var l int
+	_ = l
+	if m.Type != 0 {
+		n += 1 + sovBalance(uint64(m.Type))
+	}
+	if m.Amount != 0 {
+		n += 1 + sovBalance(uint64(m.Amount))
+	}
+	return n
+}
+
+func sovBalance(x uint64) (n int) {
+	for {
+		n++
+		x >>= 7
+		if x == 0 {
+			break
+		}
+	}
+	return n
+}
+func sozBalance(x uint64) (n int) {
+	return sovBalance(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Balance) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowBalance
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Balance: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Balance: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
+			}
+			m.Type = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowBalance
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Type |= (Type(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType)
+			}
+			m.Amount = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowBalance
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Amount |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipBalance(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthBalance
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipBalance(dAtA []byte) (n int, err error) {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return 0, ErrIntOverflowBalance
+			}
+			if iNdEx >= l {
+				return 0, io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		wireType := int(wire & 0x7)
+		switch wireType {
+		case 0:
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowBalance
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				iNdEx++
+				if dAtA[iNdEx-1] < 0x80 {
+					break
+				}
+			}
+			return iNdEx, nil
+		case 1:
+			iNdEx += 8
+			return iNdEx, nil
+		case 2:
+			var length int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowBalance
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				length |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			iNdEx += length
+			if length < 0 {
+				return 0, ErrInvalidLengthBalance
+			}
+			return iNdEx, nil
+		case 3:
+			for {
+				var innerWire uint64
+				var start int = iNdEx
+				for shift := uint(0); ; shift += 7 {
+					if shift >= 64 {
+						return 0, ErrIntOverflowBalance
+					}
+					if iNdEx >= l {
+						return 0, io.ErrUnexpectedEOF
+					}
+					b := dAtA[iNdEx]
+					iNdEx++
+					innerWire |= (uint64(b) & 0x7F) << shift
+					if b < 0x80 {
+						break
+					}
+				}
+				innerWireType := int(innerWire & 0x7)
+				if innerWireType == 4 {
+					break
+				}
+				next, err := skipBalance(dAtA[start:])
+				if err != nil {
+					return 0, err
+				}
+				iNdEx = start + next
+			}
+			return iNdEx, nil
+		case 4:
+			return iNdEx, nil
+		case 5:
+			iNdEx += 4
+			return iNdEx, nil
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+	}
+	panic("unreachable")
+}
+
+var (
+	ErrInvalidLengthBalance = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowBalance   = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("balance.proto", fileDescriptorBalance) }
+func init() { golang_proto.RegisterFile("balance.proto", fileDescriptorBalance) }
+
+var fileDescriptorBalance = []byte{
+	// 187 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4d, 0x4a, 0xcc, 0x49,
+	0xcc, 0x4b, 0x4e, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x87, 0x72, 0xa5, 0x74, 0xd3,
+	0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5, 0xd3, 0xf3, 0xd3, 0xf3, 0xf5, 0xc1,
+	0xf2, 0x49, 0xa5, 0x69, 0x60, 0x1e, 0x98, 0x03, 0x66, 0x41, 0xf4, 0x29, 0xb9, 0x72, 0xb1, 0x3b,
+	0x41, 0x74, 0x0a, 0xc9, 0x70, 0xb1, 0x84, 0x54, 0x16, 0xa4, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xf0,
+	0x3a, 0x71, 0xfc, 0xba, 0x27, 0x0f, 0xe6, 0x07, 0x81, 0x49, 0x21, 0x31, 0x2e, 0x36, 0xc7, 0xdc,
+	0xfc, 0xd2, 0xbc, 0x12, 0x09, 0x26, 0x05, 0x46, 0x0d, 0x96, 0x20, 0x28, 0xcf, 0x8a, 0x65, 0xc6,
+	0x02, 0x79, 0x06, 0x27, 0xfb, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48,
+	0x8e, 0xf1, 0xc0, 0x63, 0x39, 0xc6, 0x13, 0x8f, 0xe5, 0x18, 0xa3, 0x34, 0x91, 0xdc, 0x92, 0x51,
+	0x59, 0x90, 0x5a, 0x94, 0x93, 0x9a, 0x92, 0x9e, 0x5a, 0xa4, 0x9f, 0x54, 0x5a, 0x54, 0x94, 0x5f,
+	0xae, 0x9f, 0x98, 0x9c, 0xab, 0x0f, 0x75, 0x76, 0x12, 0x1b, 0xd8, 0x39, 0xc6, 0x80, 0x00, 0x00,
+	0x00, 0xff, 0xff, 0x1d, 0x22, 0xfc, 0x8b, 0xd7, 0x00, 0x00, 0x00,
+}
diff --git a/acm/balance/balance_test.go b/acm/balance/balance_test.go
new file mode 100644
index 00000000..d6710e09
--- /dev/null
+++ b/acm/balance/balance_test.go
@@ -0,0 +1,22 @@
+package balance
+
+import (
+	"sort"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestSum(t *testing.T) {
+	one := New().Power(23223).Native(34).Native(1111)
+	two := New().Power(3).Native(22)
+	sum := one.Sum(two)
+	assert.Equal(t, New().Power(23226).Native(1167), sum)
+}
+
+func TestSort(t *testing.T) {
+	balances := New().Power(232).Native(2523543).Native(232).Power(2).Power(4).Native(1)
+	sortedBalances := New().Native(1).Native(232).Native(2523543).Power(2).Power(4).Power(232)
+	sort.Sort(balances)
+	assert.Equal(t, sortedBalances, balances)
+}
diff --git a/acm/balance/type.go b/acm/balance/type.go
new file mode 100644
index 00000000..8b8ece9a
--- /dev/null
+++ b/acm/balance/type.go
@@ -0,0 +1,51 @@
+package balance
+
+type Type uint32
+
+const (
+	TypeNative Type = 1
+	TypePower  Type = 2
+)
+
+var nameFromType = map[Type]string{
+	TypeNative: "Native",
+	TypePower:  "Power",
+}
+
+var typeFromName = make(map[string]Type)
+
+func init() {
+	for t, n := range nameFromType {
+		typeFromName[n] = t
+	}
+}
+
+func TypeFromString(name string) Type {
+	return typeFromName[name]
+}
+
+func (typ Type) String() string {
+	name, ok := nameFromType[typ]
+	if ok {
+		return name
+	}
+	return "UnknownBalanceType"
+}
+
+func (typ Type) MarshalText() ([]byte, error) {
+	return []byte(typ.String()), nil
+}
+
+func (typ *Type) UnmarshalText(data []byte) error {
+	*typ = TypeFromString(string(data))
+	return nil
+}
+
+// Protobuf support
+func (typ Type) Marshal() ([]byte, error) {
+	return typ.MarshalText()
+}
+
+func (typ *Type) Unmarshal(data []byte) error {
+	return typ.UnmarshalText(data)
+}
diff --git a/acm/validator.go b/acm/validator.go
deleted file mode 100644
index ddf471ec..00000000
--- a/acm/validator.go
+++ /dev/null
@@ -1,92 +0,0 @@
-package acm
-
-import (
-	"encoding/json"
-
-	"github.com/hyperledger/burrow/crypto"
-)
-
-type Validator interface {
-	crypto.Addressable
-	// The validator's voting power
-	Power() uint64
-}
-
-// Neither abci_types or tm_types has quite the representation we want
-type ConcreteValidator struct {
-	Address   crypto.Address
-	PublicKey crypto.PublicKey
-	Power     uint64
-}
-
-type concreteValidatorWrapper struct {
-	*ConcreteValidator `json:"unwrap"`
-}
-
-var _ Validator = concreteValidatorWrapper{}
-
-func AsValidator(account Account) Validator {
-	return ConcreteValidator{
-		Address:   account.Address(),
-		PublicKey: account.PublicKey(),
-		Power:     account.Balance(),
-	}.Validator()
-}
-
-func AsConcreteValidator(validator Validator) *ConcreteValidator {
-	if validator == nil {
-		return nil
-	}
-	if ca, ok := validator.(concreteValidatorWrapper); ok {
-		return ca.ConcreteValidator
-	}
-	return &ConcreteValidator{
-		Address:   validator.Address(),
-		PublicKey: validator.PublicKey(),
-		Power:     validator.Power(),
-	}
-}
-
-func (cvw concreteValidatorWrapper) Address() crypto.Address {
-	return cvw.ConcreteValidator.Address
-}
-
-func (cvw concreteValidatorWrapper) PublicKey() crypto.PublicKey {
-	return cvw.ConcreteValidator.PublicKey
-}
-
-func (cvw concreteValidatorWrapper) Power() uint64 {
-	return cvw.ConcreteValidator.Power
-}
-
-func (cvw concreteValidatorWrapper) WithNewPower(power uint64) Validator {
-	cv := cvw.Copy()
-	cv.Power = power
-	return concreteValidatorWrapper{
-		ConcreteValidator: cv,
-	}
-}
-
-func (cv ConcreteValidator) Validator() Validator {
-	return concreteValidatorWrapper{
-		ConcreteValidator: &cv,
-	}
-}
-
-func (cv *ConcreteValidator) Copy() *ConcreteValidator {
-	cvCopy := *cv
-	return &cvCopy
-}
-
-func (cv *ConcreteValidator) String() string {
-	if cv == nil {
-		return "Nil Validator"
-	}
-
-	bs, err := json.Marshal(cv)
-	if err != nil {
-		return "error serialising Validator"
-	}
-
-	return string(bs)
-}
diff --git a/acm/validator/ring.go b/acm/validator/ring.go
new file mode 100644
index 00000000..bbc6fa56
--- /dev/null
+++ b/acm/validator/ring.go
@@ -0,0 +1,265 @@
+package validator
+
+import (
+	"fmt"
+	"math/big"
+
+	"github.com/hyperledger/burrow/crypto"
+)
+
+type Ring struct {
+	// The validator power history stored in buckets as a ring buffer
+	// The changes committed at rotation i
+	delta []*Set
+	// The cumulative changes at rotation i - 1
+	cum []*Set
+	// Totals for each validator across all buckets
+	power *Set
+	// Current flow totals for each validator in the Head bucket
+	flow *Set
+	// Index of current head bucket
+	head int64
+	// Number of buckets
+	size int64
+}
+
+var big1 = big.NewInt(1)
+var big3 = big.NewInt(3)
+
+// Provides a sliding window over the last size buckets of validator power changes
+func NewRing(initialSet Iterable, windowSize int) *Ring {
+	if windowSize < 1 {
+		windowSize = 1
+	}
+	vw := &Ring{
+		delta: make([]*Set, windowSize),
+		cum:   make([]*Set, windowSize),
+		power: NewSet(),
+		flow:  NewSet(),
+		size:  int64(windowSize),
+	}
+	for i := 0; i < windowSize; i++ {
+		vw.delta[i] = NewSet()
+		// Important that this is trim set for accurate count
+		vw.cum[i] = NewTrimSet()
+	}
+	vw.cum[0] = Copy(initialSet)
+
+	return vw
+}
+
+// Implement Reader
+// Get power at index from the delta bucket then falling through to the cumulative
+func (vc *Ring) PowerAt(index int64, id crypto.Addressable) *big.Int {
+	power := vc.Head().MaybePower(id)
+	if power != nil {
+		return power
+	}
+	return vc.Cum().Power(id)
+}
+
+func (vc *Ring) Power(id crypto.Addressable) *big.Int {
+	return vc.PowerAt(vc.head, id)
+}
+
+// Return the resultant set at index of current cum plus delta
+func (vc *Ring) Resultant(index int64) *Set {
+	i := vc.index(index)
+	cum := CopyTrim(vc.cum[i])
+	vc.delta[i].Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) {
+		cum.AlterPower(id, power)
+		return
+	})
+	return cum
+}
+
+func (vc *Ring) TotalPower() *big.Int {
+	return vc.Resultant(vc.head).totalPower
+}
+
+// Updates the current head bucket (accumulator) with some safety checks
+func (vc *Ring) AlterPower(id crypto.Addressable, power *big.Int) (*big.Int, error) {
+	if power.Sign() == -1 {
+		return nil, fmt.Errorf("cannot set negative validator power: %v", power)
+	}
+	if !power.IsInt64() {
+		return nil, fmt.Errorf("for tendermint compatibility validator power must fit within an Int64 bur %v "+
+			"does not", power)
+	}
+	// if flow > maxflow then we cannot alter the power
+	flow := vc.Flow(id, power)
+	maxFlow := vc.MaxFlow()
+	// Set flow for this id to update flow.totalPower (total flow) for comparison below, keep track of flow for each id
+	// so that we only count flow once for each id
+	vc.flow.ChangePower(id, flow)
+	// The totalPower of the Flow Set is the absolute value of all power changes made so far
+	if vc.flow.totalPower.Cmp(maxFlow) == 1 {
+		// Reset flow to previous value to undo update above
+		prevFlow := vc.Flow(id, vc.Head().Power(id))
+		vc.flow.ChangePower(id, prevFlow)
+		allowable := new(big.Int).Sub(maxFlow, vc.flow.totalPower)
+		return nil, fmt.Errorf("cannot change validator power of %v from %v to %v because that would result in a flow "+
+			"greater than or equal to 1/3 of total power for the next commit: flow induced by change: %v, "+
+			"current total flow: %v/%v (cumulative/max), remaining allowable flow: %v",
+			id.Address(), vc.Cum().Power(id), power, flow, vc.flow.totalPower, maxFlow, allowable)
+	}
+	// Add to total power
+	vc.Head().ChangePower(id, power)
+	return flow, nil
+}
+
+// Returns the flow that would be induced by a validator change by comparing the head accumulater with the current set
+func (vc *Ring) Flow(id crypto.Addressable, power *big.Int) *big.Int {
+	flow := new(big.Int)
+	return flow.Abs(flow.Sub(power, vc.Cum().Power(id)))
+}
+
+// To ensure that in the maximum valildator shift at least one unit
+// of validator power in the intersection of last block validators and this block validators must have at least one
+// non-byzantine validator who can tell you if you've been lied to about the validator set
+// So need at most ceiling((Total Power)/3) - 1, in integer division we have ceiling(X*p/q) = (p(X+1)-1)/q
+// For p = 1 just X/q
+// So we want (Total Power)/3 - 1
+func (vc *Ring) MaxFlow() *big.Int {
+	max := vc.Cum().TotalPower()
+	return max.Sub(max.Div(max, big3), big1)
+}
+
+// Advance the current head bucket to the next bucket and returns the change in total power between the previous bucket
+// and the current head, and the total flow which is the sum of absolute values of all changes each validator's power
+// after rotation the next head is a copy of the current head
+func (vc *Ring) Rotate() (totalPowerChange *big.Int, totalFlow *big.Int, err error) {
+	// Subtract the tail bucket (if any) from the total
+	err = Subtract(vc.power, vc.Next())
+	if err != nil {
+		return
+	}
+	// Add head delta to total power
+	err = Add(vc.power, vc.Head())
+	if err != nil {
+		return
+	}
+	// Copy current cumulative bucket
+	cum := CopyTrim(vc.Cum())
+	// Copy delta into what will be the next cumulative bucket
+	err = Alter(cum, vc.Head())
+	if err != nil {
+		return
+	}
+	// Advance the ring buffer
+	vc.head = vc.index(1)
+	// Overwrite new head bucket (previous tail) with a fresh delta accumulator
+	vc.delta[vc.head] = NewSet()
+	// Set the next cum
+	vc.cum[vc.head] = cum
+	// Capture flow before we wipe it
+	totalFlow = vc.flow.totalPower
+	// New flow accumulator
+	vc.flow = NewSet()
+	// Subtract the previous bucket total power so we can add on the current buckets power after this
+	totalPowerChange = new(big.Int).Sub(vc.Cum().TotalPower(), vc.cum[vc.index(-1)].TotalPower())
+	return
+}
+
+func (vc *Ring) CurrentSet() *Set {
+	return vc.cum[vc.head]
+}
+
+func (vc *Ring) PreviousSet() *Set {
+	return vc.cum[vc.index(-1)]
+}
+
+func (vc *Ring) Cum() *Set {
+	return vc.cum[vc.head]
+}
+
+// Get the current accumulator bucket
+func (vc *Ring) Head() *Set {
+	return vc.delta[vc.head]
+}
+
+func (vc *Ring) Next() *Set {
+	return vc.delta[vc.index(1)]
+}
+
+func (vc *Ring) index(i int64) int64 {
+	idx := (vc.size + vc.head + i) % vc.size
+	return idx
+}
+
+// Get the number of buckets in the ring (use Current().Count() to get the current number of validators)
+func (vc *Ring) Size() int64 {
+	return vc.size
+}
+
+// Returns buckets in order head, previous, ...
+func (vc *Ring) OrderedBuckets() (delta, cum []*Set) {
+	delta = make([]*Set, len(vc.delta))
+	cum = make([]*Set, len(vc.cum))
+	for i := int64(0); i < vc.size; i++ {
+		index := vc.index(-i)
+		delta[i] = vc.delta[index]
+		cum[i] = vc.cum[index]
+	}
+	return
+}
+
+func (vc *Ring) String() string {
+	delta, _ := vc.OrderedBuckets()
+	return fmt.Sprintf("ValidatorsWindow{Total: %v; Delta: Head->%v<-Tail}", vc.power, delta)
+}
+
+func (vc *Ring) Equal(vwOther *Ring) bool {
+	if vc.size != vwOther.size || vc.head != vwOther.head || len(vc.delta) != len(vwOther.delta) ||
+		!vc.flow.Equal(vwOther.flow) || !vc.power.Equal(vwOther.power) {
+		return false
+	}
+	for i := 0; i < len(vc.delta); i++ {
+		if !vc.delta[i].Equal(vwOther.delta[i]) || !vc.cum[i].Equal(vwOther.cum[i]) {
+			return false
+		}
+	}
+	return true
+}
+
+type PersistedRing struct {
+	Delta [][]*Validator
+	Cum   [][]*Validator
+	Power []*Validator
+	Flow  []*Validator
+	Head  int64
+}
+
+func (vc *Ring) Persistable() PersistedRing {
+	delta := make([][]*Validator, len(vc.delta))
+	cum := make([][]*Validator, len(vc.cum))
+	for i := 0; i < len(delta); i++ {
+		delta[i] = vc.delta[i].Validators()
+		cum[i] = vc.cum[i].Validators()
+
+	}
+	return PersistedRing{
+		Delta: delta,
+		Cum:   cum,
+		Power: vc.power.Validators(),
+		Flow:  vc.flow.Validators(),
+		Head:  vc.head,
+	}
+}
+
+func UnpersistRing(pc PersistedRing) *Ring {
+	delta := make([]*Set, len(pc.Delta))
+	cum := make([]*Set, len(pc.Cum))
+	for i := 0; i < len(delta); i++ {
+		delta[i] = UnpersistSet(pc.Delta[i])
+		cum[i] = UnpersistSet(pc.Cum[i])
+	}
+	return &Ring{
+		delta: delta,
+		cum:   cum,
+		head:  pc.Head,
+		power: UnpersistSet(pc.Power),
+		flow:  UnpersistSet(pc.Flow),
+		size:  int64(len(delta)),
+	}
+}
diff --git a/blockchain/validators_ring_test.go b/acm/validator/ring_test.go
similarity index 86%
rename from blockchain/validators_ring_test.go
rename to acm/validator/ring_test.go
index d0c81628..66d00db9 100644
--- a/blockchain/validators_ring_test.go
+++ b/acm/validator/ring_test.go
@@ -1,4 +1,4 @@
-package blockchain
+package validator
 
 import (
 	"fmt"
@@ -14,10 +14,12 @@ var pubB = pubKey(2)
 var pubC = pubKey(3)
 
 func TestValidatorsWindow_AlterPower(t *testing.T) {
-	vs := NewValidators()
+	vsBase := NewSet()
 	powAInitial := int64(10000)
-	vs.AlterPower(pubA, big.NewInt(powAInitial))
-	vw := NewValidatorsRing(vs, 3)
+	vsBase.ChangePower(pubA, big.NewInt(powAInitial))
+
+	vs := Copy(vsBase)
+	vw := NewRing(vs, 3)
 
 	// Just allowable validator tide
 	var powA, powB, powC int64 = 7000, 23, 309
@@ -27,7 +29,8 @@ func TestValidatorsWindow_AlterPower(t *testing.T) {
 	assert.Equal(t, big.NewInt(powAInitial/3-1), totalFlow)
 
 	// This one is not
-	vw = NewValidatorsRing(vs, 5)
+	vs = Copy(vsBase)
+	vw = NewRing(vs, 5)
 	powA, powB, powC = 7000, 23, 310
 	powerChange, totalFlow, err = alterPowers(t, vw, powA, powB, powC)
 	require.Error(t, err)
@@ -77,21 +80,21 @@ func TestValidatorsWindow_AlterPower(t *testing.T) {
 
 func TestValidatorsRing_Persistable(t *testing.T) {
 
-	vs := NewValidators()
+	vs := NewSet()
 	powAInitial := int64(10000)
-	vs.AlterPower(pubA, big.NewInt(powAInitial))
-	vw := NewValidatorsRing(vs, 30)
+	vs.ChangePower(pubA, big.NewInt(powAInitial))
+	vw := NewRing(vs, 30)
 
 	for i := int64(0); i < 61; i++ {
 		_, _, err := alterPowers(t, vw, 10000, 200*i, 200*((i+1)%4))
 		require.NoError(t, err)
 	}
 
-	vwOut := UnpersistValidatorsRing(vw.Persistable())
+	vwOut := UnpersistRing(vw.Persistable())
 	assert.True(t, vw.Equal(vwOut), "should re equal across persistence")
 }
 
-func alterPowers(t testing.TB, vw *ValidatorsRing, powA, powB, powC int64) (powerChange, totalFlow *big.Int, err error) {
+func alterPowers(t testing.TB, vw *Ring, powA, powB, powC int64) (powerChange, totalFlow *big.Int, err error) {
 	fmt.Println(vw)
 	_, err = vw.AlterPower(pubA, big.NewInt(powA))
 	if err != nil {
@@ -106,7 +109,8 @@ func alterPowers(t testing.TB, vw *ValidatorsRing, powA, powB, powC int64) (powe
 		return nil, nil, err
 	}
 	maxFlow := vw.MaxFlow()
-	powerChange, totalFlow = vw.Rotate()
+	powerChange, totalFlow, err = vw.Rotate()
+	require.NoError(t, err)
 	// totalFlow > maxFlow
 	if totalFlow.Cmp(maxFlow) == 1 {
 		return powerChange, totalFlow, fmt.Errorf("totalFlow (%v) exceeds maxFlow (%v)", totalFlow, maxFlow)
diff --git a/blockchain/validators.go b/acm/validator/set.go
similarity index 51%
rename from blockchain/validators.go
rename to acm/validator/set.go
index ea2ddfd4..1ce7d010 100644
--- a/blockchain/validators.go
+++ b/acm/validator/set.go
@@ -1,4 +1,4 @@
-package blockchain
+package validator
 
 import (
 	"fmt"
@@ -12,80 +12,76 @@ import (
 var big0 = big.NewInt(0)
 
 // A Validator multiset - can be used to capture the global state of validators or as an accumulator each block
-type Validators struct {
+type Set struct {
 	powers     map[crypto.Address]*big.Int
 	publicKeys map[crypto.Address]crypto.Addressable
 	totalPower *big.Int
+	trim       bool
 }
 
-type ValidatorSet interface {
-	AlterPower(id crypto.Addressable, power *big.Int) (flow *big.Int, err error)
-}
-
-// Create a new Validators which can act as an accumulator for validator power changes
-func NewValidators() *Validators {
-	return &Validators{
+func newSet() *Set {
+	return &Set{
 		totalPower: new(big.Int),
 		powers:     make(map[crypto.Address]*big.Int),
 		publicKeys: make(map[crypto.Address]crypto.Addressable),
 	}
 }
 
+// Create a new Validators which can act as an accumulator for validator power changes
+func NewSet() *Set {
+	return newSet()
+}
+
+// Like Set but removes entries when power is set to 0 this make Count() == CountNonZero() and prevents a set from leaking
+// but does mean that a zero will not be iterated over when performing an update which is necessary in Ring
+func NewTrimSet() *Set {
+	s := newSet()
+	s.trim = true
+	return s
+}
+
+// Implements Writer, but will never error
+func (vs *Set) AlterPower(id crypto.Addressable, power *big.Int) (flow *big.Int, err error) {
+	return vs.ChangePower(id, power), nil
+}
+
 // Add the power of a validator and returns the flow into that validator
-func (vs *Validators) AlterPower(id crypto.Addressable, power *big.Int) *big.Int {
-	if power.Sign() == -1 {
-		panic("ASRRRH")
-	}
+func (vs *Set) ChangePower(id crypto.Addressable, power *big.Int) *big.Int {
 	address := id.Address()
 	// Calculcate flow into this validator (postive means in, negative means out)
 	flow := new(big.Int).Sub(power, vs.Power(id))
 	vs.totalPower.Add(vs.totalPower, flow)
-	if power.Cmp(big0) == 0 {
-		// Remove from set so that we return an accurate length
+
+	if vs.trim && power.Sign() == 0 {
 		delete(vs.publicKeys, address)
 		delete(vs.powers, address)
-		return flow
+	} else {
+		vs.publicKeys[address] = crypto.MemoizeAddressable(id)
+		vs.powers[address] = new(big.Int).Set(power)
 	}
-	vs.publicKeys[address] = crypto.MemoizeAddressable(id)
-	vs.powers[address] = new(big.Int).Set(power)
 	return flow
 }
 
-// Adds vsOther to vs
-func (vs *Validators) Add(vsOther *Validators) {
-	vsOther.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) {
-		vs.AddPower(id, power)
-		return
-	})
-}
-
-func (vs *Validators) AddPower(id crypto.Addressable, power *big.Int) {
-	// Current power + power
-	vs.AlterPower(id, new(big.Int).Add(vs.Power(id), power))
-}
-
-// Subtracts vsOther from vs
-func (vs *Validators) Subtract(vsOther *Validators) {
-	vsOther.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) {
-		vs.SubtractPower(id, power)
-		return
-	})
+func (vs *Set) TotalPower() *big.Int {
+	return new(big.Int).Set(vs.totalPower)
 }
 
-func (vs *Validators) SubtractPower(id crypto.Addressable, power *big.Int) {
-	// Current power - power
-	thisPower := vs.Power(id)
-	vs.AlterPower(id, new(big.Int).Sub(thisPower, power))
+// Returns the power of id but only if it is set
+func (vs *Set) MaybePower(id crypto.Addressable) *big.Int {
+	if vs.powers[id.Address()] == nil {
+		return nil
+	}
+	return new(big.Int).Set(vs.powers[id.Address()])
 }
 
-func (vs *Validators) Power(id crypto.Addressable) *big.Int {
+func (vs *Set) Power(id crypto.Addressable) *big.Int {
 	if vs.powers[id.Address()] == nil {
 		return new(big.Int)
 	}
 	return new(big.Int).Set(vs.powers[id.Address()])
 }
 
-func (vs *Validators) Equal(vsOther *Validators) bool {
+func (vs *Set) Equal(vsOther *Set) bool {
 	if vs.Count() != vsOther.Count() {
 		return false
 	}
@@ -100,7 +96,7 @@ func (vs *Validators) Equal(vsOther *Validators) bool {
 }
 
 // Iterates over validators sorted by address
-func (vs *Validators) Iterate(iter func(id crypto.Addressable, power *big.Int) (stop bool)) (stopped bool) {
+func (vs *Set) Iterate(iter func(id crypto.Addressable, power *big.Int) (stop bool)) (stopped bool) {
 	if vs == nil {
 		return
 	}
@@ -117,55 +113,47 @@ func (vs *Validators) Iterate(iter func(id crypto.Addressable, power *big.Int) (
 	return
 }
 
-func (vs *Validators) Count() int {
-	return len(vs.publicKeys)
-}
-
-func (vs *Validators) TotalPower() *big.Int {
-	return new(big.Int).Set(vs.totalPower)
-}
-
-func (vs *Validators) Copy() *Validators {
-	vsCopy := NewValidators()
+func (vs *Set) CountNonZero() int {
+	var count int
 	vs.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) {
-		vsCopy.AlterPower(id, power)
+		if power.Sign() != 0 {
+			count++
+		}
 		return
 	})
-	return vsCopy
+	return count
 }
 
-type PersistedValidator struct {
-	PublicKey  crypto.PublicKey
-	PowerBytes []byte
+func (vs *Set) Count() int {
+	return len(vs.publicKeys)
 }
 
-func (vs *Validators) Persistable() []PersistedValidator {
+func (vs *Set) Validators() []*Validator {
 	if vs == nil {
 		return nil
 	}
-	pvs := make([]PersistedValidator, 0, vs.Count())
+	pvs := make([]*Validator, 0, vs.Count())
 	vs.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) {
-		pvs = append(pvs, PersistedValidator{PublicKey: id.PublicKey(), PowerBytes: power.Bytes()})
+		pvs = append(pvs, &Validator{PublicKey: id.PublicKey(), Power: power.Uint64()})
 		return
 	})
 	return pvs
 }
 
-func UnpersistValidators(pvs []PersistedValidator) *Validators {
-	vs := NewValidators()
+func UnpersistSet(pvs []*Validator) *Set {
+	vs := NewSet()
 	for _, pv := range pvs {
-		power := new(big.Int).SetBytes(pv.PowerBytes)
-		vs.AlterPower(pv.PublicKey, power)
+		vs.ChangePower(pv.PublicKey, new(big.Int).SetUint64(pv.Power))
 	}
 	return vs
 }
 
-func (vs *Validators) String() string {
+func (vs *Set) String() string {
 	return fmt.Sprintf("Validators{TotalPower: %v; Count: %v; %v}", vs.TotalPower(), vs.Count(),
-		vs.ValidatorStrings())
+		vs.Strings())
 }
 
-func (vs *Validators) ValidatorStrings() string {
+func (vs *Set) Strings() string {
 	strs := make([]string, 0, vs.Count())
 	vs.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) {
 		strs = append(strs, fmt.Sprintf("%v->%v", id.Address(), power))
diff --git a/blockchain/validators_test.go b/acm/validator/set_test.go
similarity index 81%
rename from blockchain/validators_test.go
rename to acm/validator/set_test.go
index 1bc7970e..ea0eeb63 100644
--- a/blockchain/validators_test.go
+++ b/acm/validator/set_test.go
@@ -1,4 +1,4 @@
-package blockchain
+package validator
 
 import (
 	"fmt"
@@ -11,12 +11,12 @@ import (
 )
 
 func TestValidators_AlterPower(t *testing.T) {
-	vs := NewValidators()
+	vs := NewSet()
 	pow1 := big.NewInt(2312312321)
 	pubA := pubKey(1)
-	vs.AlterPower(pubA, pow1)
+	vs.ChangePower(pubA, pow1)
 	assert.Equal(t, pow1, vs.TotalPower())
-	vs.AlterPower(pubA, big.NewInt(0))
+	vs.ChangePower(pubA, big.NewInt(0))
 	assertZero(t, vs.TotalPower())
 }
 
diff --git a/acm/validator/validator.go b/acm/validator/validator.go
new file mode 100644
index 00000000..d2bdc174
--- /dev/null
+++ b/acm/validator/validator.go
@@ -0,0 +1,27 @@
+package validator
+
+import (
+	"fmt"
+
+	"github.com/hyperledger/burrow/acm"
+)
+
+func (v Validator) String() string {
+	return fmt.Sprintf("Validator{Address: %v, PublicKey: %v, Power: %v}", v.Address, v.PublicKey, v.Power)
+}
+
+func (v Validator) FillAddress() {
+	if v.Address == nil {
+		address := v.PublicKey.Address()
+		v.Address = &address
+	}
+}
+
+func FromAccount(acc acm.Account, power uint64) Validator {
+	address := acc.Address()
+	return Validator{
+		Address:   &address,
+		PublicKey: acc.PublicKey(),
+		Power:     power,
+	}
+}
diff --git a/acm/validator/validator.pb.go b/acm/validator/validator.pb.go
new file mode 100644
index 00000000..93c8b77d
--- /dev/null
+++ b/acm/validator/validator.pb.go
@@ -0,0 +1,405 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: validator.proto
+
+/*
+	Package validator is a generated protocol buffer package.
+
+	It is generated from these files:
+		validator.proto
+
+	It has these top-level messages:
+		Validator
+*/
+package validator
+
+import proto "github.com/gogo/protobuf/proto"
+import golang_proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+import _ "github.com/gogo/protobuf/gogoproto"
+import _ "github.com/hyperledger/burrow/permission"
+import crypto "github.com/hyperledger/burrow/crypto"
+
+import github_com_hyperledger_burrow_crypto "github.com/hyperledger/burrow/crypto"
+
+import io "io"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = golang_proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
+
+type Validator struct {
+	Address   *github_com_hyperledger_burrow_crypto.Address `protobuf:"bytes,1,opt,name=Address,proto3,customtype=github.com/hyperledger/burrow/crypto.Address" json:"Address,omitempty"`
+	PublicKey crypto.PublicKey                              `protobuf:"bytes,2,opt,name=PublicKey" json:"PublicKey"`
+	Power     uint64                                        `protobuf:"varint,3,opt,name=Power,proto3" json:"Power,omitempty"`
+}
+
+func (m *Validator) Reset()                    { *m = Validator{} }
+func (*Validator) ProtoMessage()               {}
+func (*Validator) Descriptor() ([]byte, []int) { return fileDescriptorValidator, []int{0} }
+
+func (m *Validator) GetPublicKey() crypto.PublicKey {
+	if m != nil {
+		return m.PublicKey
+	}
+	return crypto.PublicKey{}
+}
+
+func (m *Validator) GetPower() uint64 {
+	if m != nil {
+		return m.Power
+	}
+	return 0
+}
+
+func (*Validator) XXX_MessageName() string {
+	return "validator.Validator"
+}
+func init() {
+	proto.RegisterType((*Validator)(nil), "validator.Validator")
+	golang_proto.RegisterType((*Validator)(nil), "validator.Validator")
+}
+func (m *Validator) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalTo(dAtA)
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Validator) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if m.Address != nil {
+		dAtA[i] = 0xa
+		i++
+		i = encodeVarintValidator(dAtA, i, uint64(m.Address.Size()))
+		n1, err := m.Address.MarshalTo(dAtA[i:])
+		if err != nil {
+			return 0, err
+		}
+		i += n1
+	}
+	dAtA[i] = 0x12
+	i++
+	i = encodeVarintValidator(dAtA, i, uint64(m.PublicKey.Size()))
+	n2, err := m.PublicKey.MarshalTo(dAtA[i:])
+	if err != nil {
+		return 0, err
+	}
+	i += n2
+	if m.Power != 0 {
+		dAtA[i] = 0x18
+		i++
+		i = encodeVarintValidator(dAtA, i, uint64(m.Power))
+	}
+	return i, nil
+}
+
+func encodeVarintValidator(dAtA []byte, offset int, v uint64) int {
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return offset + 1
+}
+func (m *Validator) Size() (n int) {
+	var l int
+	_ = l
+	if m.Address != nil {
+		l = m.Address.Size()
+		n += 1 + l + sovValidator(uint64(l))
+	}
+	l = m.PublicKey.Size()
+	n += 1 + l + sovValidator(uint64(l))
+	if m.Power != 0 {
+		n += 1 + sovValidator(uint64(m.Power))
+	}
+	return n
+}
+
+func sovValidator(x uint64) (n int) {
+	for {
+		n++
+		x >>= 7
+		if x == 0 {
+			break
+		}
+	}
+	return n
+}
+func sozValidator(x uint64) (n int) {
+	return sovValidator(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Validator) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowValidator
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Validator: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Validator: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowValidator
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthValidator
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			var v github_com_hyperledger_burrow_crypto.Address
+			m.Address = &v
+			if err := m.Address.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field PublicKey", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowValidator
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthValidator
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.PublicKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Power", wireType)
+			}
+			m.Power = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowValidator
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Power |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipValidator(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthValidator
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipValidator(dAtA []byte) (n int, err error) {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return 0, ErrIntOverflowValidator
+			}
+			if iNdEx >= l {
+				return 0, io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		wireType := int(wire & 0x7)
+		switch wireType {
+		case 0:
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowValidator
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				iNdEx++
+				if dAtA[iNdEx-1] < 0x80 {
+					break
+				}
+			}
+			return iNdEx, nil
+		case 1:
+			iNdEx += 8
+			return iNdEx, nil
+		case 2:
+			var length int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowValidator
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				length |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			iNdEx += length
+			if length < 0 {
+				return 0, ErrInvalidLengthValidator
+			}
+			return iNdEx, nil
+		case 3:
+			for {
+				var innerWire uint64
+				var start int = iNdEx
+				for shift := uint(0); ; shift += 7 {
+					if shift >= 64 {
+						return 0, ErrIntOverflowValidator
+					}
+					if iNdEx >= l {
+						return 0, io.ErrUnexpectedEOF
+					}
+					b := dAtA[iNdEx]
+					iNdEx++
+					innerWire |= (uint64(b) & 0x7F) << shift
+					if b < 0x80 {
+						break
+					}
+				}
+				innerWireType := int(innerWire & 0x7)
+				if innerWireType == 4 {
+					break
+				}
+				next, err := skipValidator(dAtA[start:])
+				if err != nil {
+					return 0, err
+				}
+				iNdEx = start + next
+			}
+			return iNdEx, nil
+		case 4:
+			return iNdEx, nil
+		case 5:
+			iNdEx += 4
+			return iNdEx, nil
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+	}
+	panic("unreachable")
+}
+
+var (
+	ErrInvalidLengthValidator = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowValidator   = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("validator.proto", fileDescriptorValidator) }
+func init() { golang_proto.RegisterFile("validator.proto", fileDescriptorValidator) }
+
+var fileDescriptorValidator = []byte{
+	// 255 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2f, 0x4b, 0xcc, 0xc9,
+	0x4c, 0x49, 0x2c, 0xc9, 0x2f, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x84, 0x0b, 0x48,
+	0xe9, 0xa6, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0xa7, 0xe7, 0xa7, 0xe7,
+	0xeb, 0x83, 0x55, 0x24, 0x95, 0xa6, 0x81, 0x79, 0x60, 0x0e, 0x98, 0x05, 0xd1, 0x29, 0x25, 0x50,
+	0x90, 0x5a, 0x94, 0x9b, 0x59, 0x5c, 0x9c, 0x99, 0x9f, 0x07, 0x15, 0xe1, 0x49, 0x2e, 0xaa, 0x2c,
+	0x28, 0x81, 0xca, 0x2b, 0xad, 0x62, 0xe4, 0xe2, 0x0c, 0x83, 0x19, 0x2e, 0xe4, 0xc5, 0xc5, 0xee,
+	0x98, 0x92, 0x52, 0x94, 0x5a, 0x5c, 0x2c, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0xe3, 0x64, 0x70, 0xeb,
+	0x9e, 0xbc, 0x0e, 0x92, 0x8d, 0x19, 0x95, 0x05, 0xa9, 0x45, 0x39, 0xa9, 0x29, 0xe9, 0xa9, 0x45,
+	0xfa, 0x49, 0xa5, 0x45, 0x45, 0xf9, 0xe5, 0xfa, 0x50, 0xe3, 0xa0, 0xfa, 0x82, 0x60, 0x06, 0x08,
+	0x99, 0x72, 0x71, 0x06, 0x94, 0x26, 0xe5, 0x64, 0x26, 0x7b, 0xa7, 0x56, 0x4a, 0x30, 0x29, 0x30,
+	0x6a, 0x70, 0x1b, 0x09, 0xea, 0x41, 0x15, 0xc3, 0x25, 0x9c, 0x58, 0x4e, 0xdc, 0x93, 0x67, 0x08,
+	0x42, 0xa8, 0x14, 0x12, 0xe1, 0x62, 0x0d, 0xc8, 0x2f, 0x4f, 0x2d, 0x92, 0x60, 0x56, 0x60, 0xd4,
+	0x60, 0x09, 0x82, 0x70, 0xac, 0x58, 0x66, 0x2c, 0x90, 0x67, 0x70, 0x72, 0x3c, 0xf1, 0x48, 0x8e,
+	0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x0f, 0x3c, 0x96, 0x63, 0x3c, 0xf1, 0x58,
+	0x8e, 0x31, 0x4a, 0x1b, 0xbf, 0xfb, 0x12, 0x93, 0x73, 0xf5, 0xe1, 0xc1, 0x97, 0xc4, 0x06, 0xf6,
+	0xb6, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x1c, 0xca, 0xd9, 0x6f, 0x63, 0x01, 0x00, 0x00,
+}
diff --git a/acm/validator/validators.go b/acm/validator/validators.go
new file mode 100644
index 00000000..21313b7a
--- /dev/null
+++ b/acm/validator/validators.go
@@ -0,0 +1,111 @@
+package validator
+
+import (
+	"math/big"
+
+	"sync"
+
+	"github.com/hyperledger/burrow/crypto"
+)
+
+type Writer interface {
+	AlterPower(id crypto.Addressable, power *big.Int) (flow *big.Int, err error)
+}
+
+type Reader interface {
+	Power(id crypto.Addressable) *big.Int
+}
+
+type Iterable interface {
+	Iterate(func(id crypto.Addressable, power *big.Int) (stop bool)) (stopped bool)
+}
+
+type IterableReader interface {
+	Reader
+	Iterable
+}
+
+type ReaderWriter interface {
+	Reader
+	Writer
+}
+
+type IterableReaderWriter interface {
+	ReaderWriter
+	Iterable
+}
+
+type WriterFunc func(id crypto.Addressable, power *big.Int) (flow *big.Int, err error)
+
+func SyncWriter(locker sync.Locker, writerFunc WriterFunc) WriterFunc {
+	return WriterFunc(func(id crypto.Addressable, power *big.Int) (flow *big.Int, err error) {
+		locker.Lock()
+		defer locker.Unlock()
+		return writerFunc(id, power)
+	})
+}
+
+func (wf WriterFunc) AlterPower(id crypto.Addressable, power *big.Int) (flow *big.Int, err error) {
+	return wf(id, power)
+}
+
+func AddPower(vs ReaderWriter, id crypto.Addressable, power *big.Int) error {
+	// Current power + power
+	_, err := vs.AlterPower(id, new(big.Int).Add(vs.Power(id), power))
+	return err
+}
+
+func SubtractPower(vs ReaderWriter, id crypto.Addressable, power *big.Int) error {
+	_, err := vs.AlterPower(id, new(big.Int).Sub(vs.Power(id), power))
+	return err
+}
+
+func Alter(vs Writer, vsOther Iterable) (err error) {
+	vsOther.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) {
+		_, err = vs.AlterPower(id, power)
+		if err != nil {
+			return true
+		}
+		return
+	})
+	return
+}
+
+// Adds vsOther to vs
+func Add(vs ReaderWriter, vsOther Iterable) (err error) {
+	vsOther.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) {
+		err = AddPower(vs, id, power)
+		if err != nil {
+			return true
+		}
+		return
+	})
+	return
+}
+
+// Subtracts vsOther from vs
+func Subtract(vs ReaderWriter, vsOther Iterable) (err error) {
+	vsOther.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) {
+		err = SubtractPower(vs, id, power)
+		if err != nil {
+			return true
+		}
+		return
+	})
+	return
+}
+
+func Copy(vs Iterable) *Set {
+	vsCopy := NewSet()
+	vs.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) {
+		vsCopy.ChangePower(id, power)
+		return
+	})
+	return vsCopy
+}
+
+func CopyTrim(vs Iterable) *Set {
+	s := Copy(vs)
+	s.trim = true
+	return s
+}
diff --git a/acm/validator_test.go b/acm/validator_test.go
deleted file mode 100644
index 51299081..00000000
--- a/acm/validator_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package acm
diff --git a/blockchain/blockchain.go b/bcm/blockchain.go
similarity index 53%
rename from blockchain/blockchain.go
rename to bcm/blockchain.go
index 43be5ca7..d12afd6f 100644
--- a/blockchain/blockchain.go
+++ b/bcm/blockchain.go
@@ -12,16 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package blockchain
+package bcm
 
 import (
 	"bytes"
 	"fmt"
 	"math/big"
-	"sync"
 	"time"
 
-	"github.com/hyperledger/burrow/crypto"
+	"sync"
+
+	"github.com/hyperledger/burrow/acm/validator"
 	"github.com/hyperledger/burrow/genesis"
 	"github.com/hyperledger/burrow/logging"
 	"github.com/tendermint/go-amino"
@@ -33,55 +34,44 @@ const DefaultValidatorsWindowSize = 10
 
 var stateKey = []byte("BlockchainState")
 
-type TipInfo interface {
+type BlockchainInfo interface {
+	GenesisHash() []byte
+	GenesisDoc() genesis.GenesisDoc
 	ChainID() string
 	LastBlockHeight() uint64
 	LastBlockTime() time.Time
 	LastBlockHash() []byte
 	AppHashAfterLastBlock() []byte
-	IterateValidators(iter func(id crypto.Addressable, power *big.Int) (stop bool)) (stopped bool)
+	Validators() validator.IterableReader
+	ValidatorsHistory() (currentSet *validator.Set, deltas []*validator.Set, height uint64)
 	NumValidators() int
 }
 
-type BlockchainInfo interface {
-	TipInfo
-	GenesisHash() []byte
-	GenesisDoc() genesis.GenesisDoc
-}
-
-type Root struct {
-	genesisHash []byte
-	genesisDoc  genesis.GenesisDoc
-}
-
-type Tip struct {
+type Blockchain struct {
+	sync.RWMutex
+	db                    dbm.DB
+	genesisHash           []byte
+	genesisDoc            genesis.GenesisDoc
 	chainID               string
 	lastBlockHeight       uint64
 	lastBlockTime         time.Time
 	lastBlockHash         []byte
 	appHashAfterLastBlock []byte
-	validators            *ValidatorsRing
+	validatorCache        *validator.Ring
+	validatorCheckCache   *validator.Ring
 }
 
-type Blockchain struct {
-	*Root
-	*Tip
-	sync.RWMutex
-	db dbm.DB
-}
-
-var _ TipInfo = &Blockchain{}
+var _ BlockchainInfo = &Blockchain{}
 
 type PersistedState struct {
 	AppHashAfterLastBlock []byte
 	LastBlockHeight       uint64
 	GenesisDoc            genesis.GenesisDoc
-	Validators            PersistedValidatorsRing
+	ValidatorSet          []validator.Validator
+	ValidatorCache        validator.PersistedRing
 }
 
-func LoadOrNewBlockchain(db dbm.DB, genesisDoc *genesis.GenesisDoc,
-	logger *logging.Logger) (*Blockchain, error) {
-
+func LoadOrNewBlockchain(db dbm.DB, genesisDoc *genesis.GenesisDoc, logger *logging.Logger) (*Blockchain, error) {
 	logger = logger.WithScope("LoadOrNewBlockchain")
 	logger.InfoMsg("Trying to load blockchain state from database",
 		"database_key", stateKey)
@@ -94,7 +84,8 @@ func LoadOrNewBlockchain(db dbm.DB, genesisDoc *genesis.GenesisDoc,
 		argHash := genesisDoc.Hash()
 		if !bytes.Equal(dbHash, argHash) {
 			return nil, fmt.Errorf("GenesisDoc passed to LoadOrNewBlockchain has hash: 0x%X, which does not "+
-				"match the one found in database: 0x%X", argHash, dbHash)
+				"match the one found in database: 0x%X, database genesis:\n%v\npassed genesis:\n%v\n",
+				argHash, dbHash, bc.genesisDoc.JSONString(), genesisDoc.JSONString())
 		}
 		return bc, nil
 	}
@@ -105,15 +96,19 @@ func LoadOrNewBlockchain(db dbm.DB, genesisDoc *genesis.GenesisDoc,
 
 // Pointer to blockchain state initialised from genesis
 func newBlockchain(db dbm.DB, genesisDoc *genesis.GenesisDoc) *Blockchain {
-	vs := NewValidators()
+	vs := validator.NewTrimSet()
 	for _, gv := range genesisDoc.Validators {
-		vs.AlterPower(gv.PublicKey, new(big.Int).SetUint64(gv.Amount))
+		vs.ChangePower(gv.PublicKey, new(big.Int).SetUint64(gv.Amount))
 	}
-	root := NewRoot(genesisDoc)
 	bc := &Blockchain{
-		db:   db,
-		Root: root,
-		Tip:  NewTip(genesisDoc.ChainID(), root.genesisDoc.GenesisTime, root.genesisHash, vs),
+		db:                    db,
+		genesisHash:           genesisDoc.Hash(),
+		genesisDoc:            *genesisDoc,
+		chainID:               genesisDoc.ChainID(),
+		lastBlockTime:         genesisDoc.GenesisTime,
+		appHashAfterLastBlock: genesisDoc.Hash(),
+		validatorCache:        validator.NewRing(vs, DefaultValidatorsWindowSize),
+		validatorCheckCache:   validator.NewRing(vs, 1),
 	}
 	return bc
 }
@@ -131,50 +126,38 @@ func loadBlockchain(db dbm.DB) (*Blockchain, error) {
 	return bc, nil
 }
 
-func NewRoot(genesisDoc *genesis.GenesisDoc) *Root {
-	return &Root{
-		genesisHash: genesisDoc.Hash(),
-		genesisDoc:  *genesisDoc,
-	}
+func (bc *Blockchain) ValidatorChecker() validator.Writer {
+	return validator.SyncWriter(bc, bc.validatorCheckCache.AlterPower)
 }
 
-// Create genesis Tip
-func NewTip(chainID string, genesisTime time.Time, genesisHash []byte, initialValidators *Validators) *Tip {
-	return &Tip{
-		chainID:               chainID,
-		lastBlockTime:         genesisTime,
-		appHashAfterLastBlock: genesisHash,
-		validators:            NewValidatorsRing(initialValidators, DefaultValidatorsWindowSize),
-	}
+func (bc *Blockchain) ValidatorWriter() validator.Writer {
+	return validator.SyncWriter(bc, bc.validatorCache.AlterPower)
 }
 
-func (bc *Blockchain) AlterPower(id crypto.Addressable, power *big.Int) (*big.Int, error) {
-	return bc.validators.AlterPower(id, power)
-}
-
-func (bc *Blockchain) CommitBlock(blockTime time.Time, blockHash, appHash []byte) error {
+func (bc *Blockchain) CommitBlock(blockTime time.Time,
+	blockHash, appHash []byte) (totalPowerChange, totalFlow *big.Int, err error) {
 	bc.Lock()
 	defer bc.Unlock()
 	// Checkpoint on the _previous_ block. If we die, this is where we will resume since we know it must have been
 	// committed since we are committing the next block. If we fall over we can resume a safe committed state and
 	// Tendermint will catch us up
-	err := bc.save()
+	err = bc.save()
+	if err != nil {
+		return
+	}
+	totalPowerChange, totalFlow, err = bc.validatorCache.Rotate()
 	if err != nil {
-		return err
+		return
 	}
-	maxFlow := bc.validators.MaxFlow()
-	// Update validator set
-	_, totalFlow := bc.validators.Rotate()
-	if totalFlow.Cmp(maxFlow) == 1 {
-		return fmt.Errorf("total flow during block was %v exceeding the maximum allowablw flow of %v - this "+
-			"should have been prevented on a per transaction basis - we cannot continue",
-			totalFlow, maxFlow)
+	_, _, err = bc.validatorCheckCache.Rotate()
+	if err != nil {
+		return
 	}
 	bc.lastBlockHeight += 1
 	bc.lastBlockTime = blockTime
 	bc.lastBlockHash = blockHash
 	bc.appHashAfterLastBlock = appHash
-	return nil
+	return
 }
 
 func (bc *Blockchain) save() error {
@@ -195,7 +178,7 @@ func (bc *Blockchain) Encode() ([]byte, error) {
 		GenesisDoc:            bc.genesisDoc,
 		AppHashAfterLastBlock: bc.appHashAfterLastBlock,
 		LastBlockHeight:       bc.lastBlockHeight,
-		Validators:            bc.validators.Persistable(),
+		ValidatorCache:        bc.validatorCache.Persistable(),
 	}
 	encodedState, err := cdc.MarshalBinary(persistedState)
 	if err != nil {
@@ -213,46 +196,84 @@ func DecodeBlockchain(encodedState []byte) (*Blockchain, error) {
 	bc := newBlockchain(nil, &persistedState.GenesisDoc)
 	bc.lastBlockHeight = persistedState.LastBlockHeight
 	bc.appHashAfterLastBlock = persistedState.AppHashAfterLastBlock
-	bc.validators = UnpersistValidatorsRing(persistedState.Validators)
+	bc.validatorCache = validator.UnpersistRing(persistedState.ValidatorCache)
+	bc.validatorCheckCache = validator.UnpersistRing(persistedState.ValidatorCache)
 	return bc, nil
 }
 
-func (r *Root) GenesisHash() []byte {
-	return r.genesisHash
+func (bc *Blockchain) GenesisHash() []byte {
+	return bc.genesisHash
+}
+
+func (bc *Blockchain) GenesisDoc() genesis.GenesisDoc {
+	return bc.genesisDoc
+}
+
+func (bc *Blockchain) ChainID() string {
+	return bc.chainID
+}
+
+func (bc *Blockchain) LastBlockHeight() uint64 {
+	bc.RLock()
+	defer bc.RUnlock()
+	return bc.lastBlockHeight
 }
 
-func (r *Root) GenesisDoc() genesis.GenesisDoc {
-	return r.genesisDoc
+func (bc *Blockchain) LastBlockTime() time.Time {
+	bc.RLock()
+	defer bc.RUnlock()
+	return bc.lastBlockTime
 }
 
-func (t *Tip) ChainID() string {
-	return t.chainID
+func (bc *Blockchain) LastBlockHash() []byte {
+	bc.RLock()
+	defer bc.RUnlock()
+	return bc.lastBlockHash
 }
 
-func (t *Tip) LastBlockHeight() uint64 {
-	return t.lastBlockHeight
+func (bc *Blockchain) AppHashAfterLastBlock() []byte {
+	bc.RLock()
+	defer bc.RUnlock()
+	return bc.appHashAfterLastBlock
 }
 
-func (t *Tip) LastBlockTime() time.Time {
-	return t.lastBlockTime
+func (bc *Blockchain) PendingValidators() validator.IterableReader {
+	bc.RLock()
+	defer bc.RUnlock()
+	return bc.validatorCache.Head()
 }
 
-func (t *Tip) LastBlockHash() []byte {
-	return t.lastBlockHash
+func (bc *Blockchain) Validators() validator.IterableReader {
+	bc.RLock()
+	defer bc.RUnlock()
+	return bc.validatorCache.CurrentSet()
 }
 
-func (t *Tip) AppHashAfterLastBlock() []byte {
-	return t.appHashAfterLastBlock
+func (bc *Blockchain) ValidatorsHistory() (*validator.Set, []*validator.Set, uint64) {
+	bc.RLock()
+	defer bc.RUnlock()
+	delta, _ := bc.validatorCache.OrderedBuckets()
+	deltas := make([]*validator.Set, len(delta))
+	for i, d := range delta {
+		deltas[i] = validator.Copy(d)
+	}
+	return validator.CopyTrim(bc.validatorCache.CurrentSet()), deltas, bc.lastBlockHeight
 }
 
-func (t *Tip) Validators() *Validators {
-	return t.validators.Prev().Copy()
+func (bc *Blockchain) CurrentValidators() *validator.Set {
+	bc.RLock()
+	defer bc.RUnlock()
+	return bc.validatorCache.CurrentSet()
 }
 
-func (t *Tip) IterateValidators(iter func(id crypto.Addressable, power *big.Int) (stop bool)) (stopped bool) {
-	return t.validators.Prev().Copy().Iterate(iter)
+func (bc *Blockchain) PreviousValidators() *validator.Set {
+	bc.RLock()
+	defer bc.RUnlock()
+	return bc.validatorCache.PreviousSet()
 }
 
-func (t *Tip) NumValidators() int {
-	return t.validators.Prev().Count()
+func (bc *Blockchain) NumValidators() int {
+	bc.RLock()
+	defer bc.RUnlock()
+	return bc.validatorCache.CurrentSet().Count()
 }
diff --git a/blockchain/blockchain_test.go b/bcm/blockchain_test.go
similarity index 60%
rename from blockchain/blockchain_test.go
rename to bcm/blockchain_test.go
index aaa6f7ee..c5f5bc62 100644
--- a/blockchain/blockchain_test.go
+++ b/bcm/blockchain_test.go
@@ -1,4 +1,4 @@
-package blockchain
+package bcm
 
 import (
 	"fmt"
@@ -7,12 +7,14 @@ import (
 	"time"
 
 	"github.com/hyperledger/burrow/genesis"
-	"github.com/hyperledger/burrow/logging/config"
+	"github.com/hyperledger/burrow/logging/logconfig"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 	"github.com/tendermint/tendermint/libs/db"
 )
 
+var big0 = big.NewInt(0)
+
 func TestBlockchain_Encode(t *testing.T) {
 	genesisDoc, _, validators := genesis.NewDeterministicGenesis(234).
 		GenesisDoc(5, true, 232, 3, true, 34)
@@ -20,27 +22,32 @@ func TestBlockchain_Encode(t *testing.T) {
 	bs, err := bc.Encode()
 	require.NoError(t, err)
 	bcOut, err := DecodeBlockchain(bs)
-	require.True(t, bc.validators.Equal(bcOut.validators))
+	require.True(t, bc.validatorCache.Equal(bcOut.validatorCache))
 	require.Equal(t, bc.genesisDoc.GenesisTime, bcOut.genesisDoc.GenesisTime)
-	assert.Equal(t, config.JSONString(bc.genesisDoc), config.JSONString(bcOut.genesisDoc))
+	assert.Equal(t, logconfig.JSONString(bc.genesisDoc), logconfig.JSONString(bcOut.genesisDoc))
 	require.Equal(t, bc.genesisDoc.Hash(), bcOut.genesisDoc.Hash())
 	power := new(big.Int).SetUint64(genesisDoc.Validators[1].Amount)
 	id1 := validators[1].PublicKey()
 	var flow *big.Int
 	for i := 0; i < 100; i++ {
 		power := power.Div(power, big.NewInt(2))
-		flow, err = bc.AlterPower(id1, power)
+		flow, err = bc.ValidatorWriter().AlterPower(id1, power)
 		fmt.Println(flow)
 		require.NoError(t, err)
-		err = bc.CommitBlock(time.Now(), []byte("blockhash"), []byte("apphash"))
+		_, _, err = bc.CommitBlock(time.Now(), []byte("blockhash"), []byte("apphash"))
 		require.NoError(t, err)
 		bs, err = bc.Encode()
 		require.NoError(t, err)
 		bcOut, err = DecodeBlockchain(bs)
-		require.True(t, bc.validators.Equal(bcOut.validators))
+		require.True(t, bc.validatorCache.Equal(bcOut.validatorCache))
 	}
 
 	// Should have exponentially decayed to 0
 	assertZero(t, flow)
-	assertZero(t, bc.validators.Prev().Power(id1))
+	assertZero(t, bc.validatorCache.Power(id1))
+}
+
+// Since we have -0 and 0 with big.Int due to its representation with a neg flag
+func assertZero(t testing.TB, i *big.Int) {
+	assert.True(t, big0.Cmp(i) == 0, "expected 0 but got %v", i)
 }
diff --git a/blockchain/validators_ring.go b/blockchain/validators_ring.go
deleted file mode 100644
index 2709b27c..00000000
--- a/blockchain/validators_ring.go
+++ /dev/null
@@ -1,198 +0,0 @@
-package blockchain
-
-import (
-	"fmt"
-	"math/big"
-
-	"github.com/hyperledger/burrow/crypto"
-)
-
-type ValidatorsRing struct {
-	buckets []*Validators
-	// Totals for each validator across all buckets
-	power *Validators
-	// Current flow totals for each validator in the Head bucket
-	flow *Validators
-	// Index of current head bucekt
-	head int64
-	size int64
-}
-
-var big1 = big.NewInt(1)
-var big3 = big.NewInt(3)
-
-// Provides a sliding window over the last size buckets of validator power changes
-func NewValidatorsRing(initialValidators *Validators, size int) *ValidatorsRing {
-	if size < 2 {
-		size = 2
-	}
-	vw := &ValidatorsRing{
-		buckets: make([]*Validators, size),
-		power:   NewValidators(),
-		flow:    NewValidators(),
-		size:    int64(size),
-	}
-	for i := 0; i < size; i++ {
-		vw.buckets[i] = NewValidators()
-	}
-
-	initialValidators.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) {
-		// Existing set
-		vw.buckets[vw.index(-1)].AlterPower(id, power)
-		// Current accumulator
-		vw.buckets[vw.head].AlterPower(id, power)
-
-		vw.power.AddPower(id, power.Add(power, power))
-		return
-	})
-
-	return vw
-}
-
-// Updates the current head bucket (accumulator) with some safety checks
-func (vw *ValidatorsRing) AlterPower(id crypto.Addressable, power *big.Int) (*big.Int, error) {
-	if power.Sign() == -1 {
-		return nil, fmt.Errorf("cannot set negative validator power: %v", power)
-	}
-	// if flow > maxflow then we cannot alter the power
-	flow := vw.Flow(id, power)
-	maxFlow := vw.MaxFlow()
-	// Set flow to update total flow
-	vw.flow.AlterPower(id, flow)
-	if vw.flow.totalPower.Cmp(maxFlow) == 1 {
-		// Reset flow to previous value
-		vw.flow.AlterPower(id, vw.Flow(id, vw.Head().Power(id)))
-		allowable := new(big.Int).Sub(maxFlow, vw.flow.totalPower)
-		return nil, fmt.Errorf("cannot change validator power of %v from %v to %v because that would result in a flow "+
-			"greater than or equal to 1/3 of total power for the next commit: flow induced by change: %v, "+
-			"current total flow: %v/%v (cumulative/max), remaining allowable flow: %v",
-			id.Address(), vw.Prev().Power(id), power, flow, vw.flow.totalPower, maxFlow, allowable)
-	}
-	// Add to total power
-	vw.Head().AlterPower(id, power)
-	return flow, nil
-}
-
-// Returns the flow that would be induced by a validator change by comparing the current accumulator with the previous
-// bucket
-func (vw *ValidatorsRing) Flow(id crypto.Addressable, power *big.Int) *big.Int {
-	flow := new(big.Int)
-	prevPower := vw.Prev().Power(id)
-	return flow.Abs(flow.Sub(power, prevPower))
-}
-
-// To ensure that in the maximum valildator shift at least one unit
-// of validator power in the intersection of last block validators and this block validators must have at least one
-// non-byzantine validator who can tell you if you've been lied to about the validator set
-// So need at most ceiling((Total Power)/3) - 1, in integer division we have ceiling(X*p/q) = (p(X+1)-1)/q
-// For p = 1 just X/q
-// So we want (Total Power)/3 - 1
-func (vw *ValidatorsRing) MaxFlow() *big.Int {
-	max := vw.Prev().TotalPower()
-	return max.Sub(max.Div(max, big3), big1)
-}
-
-// Advance the current head bucket to the next bucket and returns the change in total power between the previous bucket
-// and the current head, and the total flow which is the sum of absolute values of all changes each validator's power
-// after rotation the next head is a copy of the current head
-func (vw *ValidatorsRing) Rotate() (totalPowerChange *big.Int, totalFlow *big.Int) {
-	// Subtract the previous bucket total power so we can add on the current buckets power after this
-	totalPowerChange = new(big.Int).Sub(vw.Head().totalPower, vw.Prev().totalPower)
-	// Capture flow before we wipe it
-	totalFlow = vw.flow.totalPower
-	// Subtract the tail bucket (if any) from the total
-	vw.power.Subtract(vw.Next())
-	// Copy head bucket
-	headCopy := vw.Head().Copy()
-	//	add it to total
-	vw.power.Add(headCopy)
-	// move the ring buffer on
-	vw.head = vw.index(1)
-	// Overwrite new head bucket (previous tail) with previous bucket copy updated with current head
-	vw.buckets[vw.head] = headCopy
-	// New flow accumulator1
-	vw.flow = NewValidators()
-	// Advance the ring
-	return totalPowerChange, totalFlow
-}
-
-func (vw *ValidatorsRing) Prev() *Validators {
-	return vw.buckets[vw.index(-1)]
-}
-
-func (vw *ValidatorsRing) Head() *Validators {
-	return vw.buckets[vw.head]
-}
-
-func (vw *ValidatorsRing) Next() *Validators {
-	return vw.buckets[vw.index(1)]
-}
-
-func (vw *ValidatorsRing) index(i int64) int64 {
-	return (vw.size + vw.head + i) % vw.size
-}
-
-func (vw *ValidatorsRing) Size() int64 {
-	return vw.size
-}
-
-// Returns buckets in order head, previous, ...
-func (vw *ValidatorsRing) OrderedBuckets() []*Validators {
-	buckets := make([]*Validators, len(vw.buckets))
-	for i := int64(0); i < vw.size; i++ {
-		buckets[i] = vw.buckets[vw.index(-i)]
-	}
-	return buckets
-}
-
-func (vw *ValidatorsRing) String() string {
-	return fmt.Sprintf("ValidatorsWindow{Total: %v; Buckets: Head->%v<-Tail}", vw.power, vw.OrderedBuckets())
-}
-
-func (vw *ValidatorsRing) Equal(vwOther *ValidatorsRing) bool {
-	if vw.size != vwOther.size || vw.head != vwOther.head || len(vw.buckets) != len(vwOther.buckets) ||
-		!vw.flow.Equal(vwOther.flow) || !vw.power.Equal(vwOther.power) {
-		return false
-	}
-	for i, b := range vw.buckets {
-		if !b.Equal(vwOther.buckets[i]) {
-			return false
-		}
-	}
-	return true
-}
-
-type PersistedValidatorsRing struct {
-	Buckets [][]PersistedValidator
-	Power   []PersistedValidator
-	Flow    []PersistedValidator
-	Head    int64
-}
-
-func (vw *ValidatorsRing) Persistable() PersistedValidatorsRing {
-	buckets := make([][]PersistedValidator, len(vw.buckets))
-	for i, vs := range vw.buckets {
-		buckets[i] = vs.Persistable()
-	}
-	return PersistedValidatorsRing{
-		Buckets: buckets,
-		Power:   vw.power.Persistable(),
-		Flow:    vw.flow.Persistable(),
-		Head:    vw.head,
-	}
-}
-
-func UnpersistValidatorsRing(pvr PersistedValidatorsRing) *ValidatorsRing {
-	buckets := make([]*Validators, len(pvr.Buckets))
-	for i, pv := range pvr.Buckets {
-		buckets[i] = UnpersistValidators(pv)
-	}
-
-	return &ValidatorsRing{
-		buckets: buckets,
-		head:    pvr.Head,
-		power:   UnpersistValidators(pvr.Power),
-		flow:    UnpersistValidators(pvr.Flow),
-		size:    int64(len(buckets)),
-	}
-}
diff --git a/cmd/burrow/commands/configure.go b/cmd/burrow/commands/configure.go
index 35788d6a..d0c149b2 100644
--- a/cmd/burrow/commands/configure.go
+++ b/cmd/burrow/commands/configure.go
@@ -15,8 +15,8 @@ import (
 	"github.com/hyperledger/burrow/genesis/spec"
 	"github.com/hyperledger/burrow/keys"
 	"github.com/hyperledger/burrow/logging"
-	logging_config "github.com/hyperledger/burrow/logging/config"
-	"github.com/hyperledger/burrow/logging/config/presets"
+	logging_config "github.com/hyperledger/burrow/logging/logconfig"
+	"github.com/hyperledger/burrow/logging/logconfig/presets"
 	cli "github.com/jawher/mow.cli"
 	amino "github.com/tendermint/go-amino"
 	tm_crypto "github.com/tendermint/tendermint/crypto"
diff --git a/cmd/burrow/commands/helpers.go b/cmd/burrow/commands/helpers.go
index ee8807e0..2ac4c741 100644
--- a/cmd/burrow/commands/helpers.go
+++ b/cmd/burrow/commands/helpers.go
@@ -9,7 +9,7 @@ import (
 	"github.com/hyperledger/burrow/config"
 	"github.com/hyperledger/burrow/config/source"
 	"github.com/hyperledger/burrow/genesis"
-	logging_config "github.com/hyperledger/burrow/logging/config"
+	logging_config "github.com/hyperledger/burrow/logging/logconfig"
 )
 
 type Output interface {
diff --git a/cmd/burrow/commands/tx.go b/cmd/burrow/commands/tx.go
new file mode 100644
index 00000000..cdff10da
--- /dev/null
+++ b/cmd/burrow/commands/tx.go
@@ -0,0 +1 @@
+package commands
diff --git a/config/config.go b/config/config.go
index c22ddbb1..8e3f7b8e 100644
--- a/config/config.go
+++ b/config/config.go
@@ -1,20 +1,18 @@
 package config
 
 import (
-	"fmt"
-
 	"context"
+	"fmt"
 
 	"github.com/hyperledger/burrow/config/source"
 	"github.com/hyperledger/burrow/consensus/tendermint"
-	"github.com/hyperledger/burrow/consensus/tendermint/validator"
 	"github.com/hyperledger/burrow/core"
 	"github.com/hyperledger/burrow/crypto"
 	"github.com/hyperledger/burrow/execution"
 	"github.com/hyperledger/burrow/genesis"
 	"github.com/hyperledger/burrow/keys"
-	logging_config "github.com/hyperledger/burrow/logging/config"
 	"github.com/hyperledger/burrow/logging/lifecycle"
+	logging_config "github.com/hyperledger/burrow/logging/logconfig"
 	"github.com/hyperledger/burrow/rpc"
 )
 
@@ -76,7 +74,7 @@ func (conf *BurrowConfig) Kernel(ctx context.Context) (*core.Kernel, error) {
 	if err != nil {
 		return nil, err
 	}
-	privValidator := validator.NewPrivValidatorMemory(val, signer)
+	privValidator := tendermint.NewPrivValidatorMemory(val, signer)
 
 	var exeOptions []execution.ExecutionOption
 	if conf.Execution != nil {
@@ -86,8 +84,8 @@ func (conf *BurrowConfig) Kernel(ctx context.Context) (*core.Kernel, error) {
 		}
 	}
 
-	return core.NewKernel(ctx, keyClient, privValidator, conf.GenesisDoc, conf.Tendermint.TendermintConfig(), conf.RPC, conf.Keys,
-		keyStore, exeOptions, logger)
+	return core.NewKernel(ctx, keyClient, privValidator, conf.GenesisDoc, conf.Tendermint.TendermintConfig(), conf.RPC,
+		conf.Keys, keyStore, exeOptions, logger)
 }
 
 func (conf *BurrowConfig) JSONString() string {
diff --git a/consensus/tendermint/abci/app.go b/consensus/tendermint/abci/app.go
index ce47eef2..cbacbc94 100644
--- a/consensus/tendermint/abci/app.go
+++ b/consensus/tendermint/abci/app.go
@@ -8,10 +8,12 @@ import (
 
 	"runtime/debug"
 
-	bcm "github.com/hyperledger/burrow/blockchain"
+	"github.com/hyperledger/burrow/acm/validator"
+	"github.com/hyperledger/burrow/bcm"
 	"github.com/hyperledger/burrow/consensus/tendermint/codes"
 	"github.com/hyperledger/burrow/crypto"
 	"github.com/hyperledger/burrow/execution"
+	errors2 "github.com/hyperledger/burrow/execution/errors"
 	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/logging/structure"
 	"github.com/hyperledger/burrow/project"
@@ -20,9 +22,9 @@ import (
 	abciTypes "github.com/tendermint/tendermint/abci/types"
 )
 
-const responseInfoName = "Burrow"
-
 type App struct {
+	// Node information to return in Info
+	nodeInfo string
 	// State
 	blockchain    *bcm.Blockchain
 	checker       execution.BatchExecutor
@@ -40,16 +42,18 @@ type App struct {
 
 var _ abciTypes.Application = &App{}
 
-func NewApp(blockchain *bcm.Blockchain, checker execution.BatchExecutor, committer execution.BatchCommitter,
+func NewApp(nodeInfo string, blockchain *bcm.Blockchain, checker execution.BatchExecutor, committer execution.BatchCommitter,
 	txDecoder txs.Decoder, panicFunc func(error), logger *logging.Logger) *App {
 	return &App{
+		nodeInfo:   nodeInfo,
 		blockchain: blockchain,
 		checker:    checker,
 		committer:  committer,
 		checkTx:    txExecutor(checker, txDecoder, logger.WithScope("CheckTx")),
 		deliverTx:  txExecutor(committer, txDecoder, logger.WithScope("DeliverTx")),
 		panicFunc:  panicFunc,
-		logger:     logger.WithScope("abci.NewApp").With(structure.ComponentKey, "ABCI_App"),
+		logger: logger.WithScope("abci.NewApp").With(structure.ComponentKey, "ABCI_App",
+			"node_info", nodeInfo),
 	}
 }
 
@@ -61,12 +65,11 @@ func (app *App) SetMempoolLocker(mempoolLocker sync.Locker) {
 }
 
 func (app *App) Info(info abciTypes.RequestInfo) abciTypes.ResponseInfo {
-	tip := app.blockchain.Tip
 	return abciTypes.ResponseInfo{
-		Data:             responseInfoName,
+		Data:             app.nodeInfo,
 		Version:          project.History.CurrentVersion().String(),
-		LastBlockHeight:  int64(tip.LastBlockHeight()),
-		LastBlockAppHash: tip.AppHashAfterLastBlock(),
+		LastBlockHeight:  int64(app.blockchain.LastBlockHeight()),
+		LastBlockAppHash: app.blockchain.AppHashAfterLastBlock(),
 	}
 }
 
@@ -88,10 +91,15 @@ func (app *App) InitChain(chain abciTypes.RequestInitChain) (respInitChain abciT
 			app.panicFunc(fmt.Errorf("panic occurred in abci.App/InitChain: %v\n%s", r, debug.Stack()))
 		}
 	}()
-	err := app.checkValidatorsMatch(chain.Validators)
-	if err != nil {
-		app.logger.InfoMsg("Initial validator set mistmatch", structure.ErrorKey, err)
-		panic(err)
+	if len(chain.Validators) != app.blockchain.NumValidators() {
+		panic(fmt.Errorf("Tendermint passes %d validators to InitChain but Burrow's Blockchain has %d",
+			len(chain.Validators), app.blockchain.NumValidators()))
+	}
+	for _, v := range chain.Validators {
+		err := app.checkValidatorMatches(app.blockchain.Validators(), v)
+		if err != nil {
+			panic(err)
+		}
 	}
 	app.logger.InfoMsg("Initial validator set matches")
 	return
@@ -105,31 +113,33 @@ func (app *App) BeginBlock(block abciTypes.RequestBeginBlock) (respBeginBlock ab
 		}
 	}()
 	if block.Header.Height > 1 {
-		validators := make([]abciTypes.Validator, len(block.Validators))
-		for i, v := range block.Validators {
-			validators[i] = v.Validator
-		}
-		err := app.checkValidatorsMatch(validators)
-		if err != nil {
+		var err error
+		// Tendermint runs a block behind with the validators passed in here
+		previousValidators := app.blockchain.PreviousValidators()
+		if len(block.Validators) != previousValidators.Count() {
+			err = fmt.Errorf("Tendermint passes %d validators to BeginBlock but Burrow's Blockchain has %d",
+				len(block.Validators), previousValidators.Count())
 			panic(err)
 		}
+		for _, v := range block.Validators {
+			err = app.checkValidatorMatches(previousValidators, v.Validator)
+			if err != nil {
+				panic(err)
+			}
+		}
 	}
 	return
 }
 
-func (app *App) checkValidatorsMatch(validators []abciTypes.Validator) error {
-	tendermintValidators := bcm.NewValidators()
-	for _, v := range validators {
-		publicKey, err := crypto.PublicKeyFromABCIPubKey(v.PubKey)
-		if err != nil {
-			panic(err)
-		}
-		tendermintValidators.AlterPower(publicKey, big.NewInt(v.Power))
+func (app *App) checkValidatorMatches(ours validator.Reader, v abciTypes.Validator) error {
+	publicKey, err := crypto.PublicKeyFromABCIPubKey(v.PubKey)
+	if err != nil {
+		return err
 	}
-	burrowValidators := app.blockchain.Validators()
-	if !burrowValidators.Equal(tendermintValidators) {
-		return fmt.Errorf("validators provided by Tendermint at InitChain do not match those held by Burrow: "+
-			"Tendermint gives: %v, Burrow gives: %v", tendermintValidators, burrowValidators)
+	power := ours.Power(publicKey)
+	if power.Cmp(big.NewInt(v.Power)) != 0 {
+		return fmt.Errorf("validator %v has power %d from Tendermint but power %d from Burrow",
+			publicKey.Address(), v.Power, power)
 	}
 	return nil
 }
@@ -137,6 +147,7 @@ func (app *App) checkValidatorsMatch(validators []abciTypes.Validator) error {
 func (app *App) CheckTx(txBytes []byte) abciTypes.ResponseCheckTx {
 	defer func() {
 		if r := recover(); r != nil {
+			fmt.Println("BeginBlock")
 			app.panicFunc(fmt.Errorf("panic occurred in abci.App/CheckTx: %v\n%s", r, debug.Stack()))
 		}
 	}()
@@ -177,19 +188,20 @@ func txExecutor(executor execution.BatchExecutor, txDecoder txs.Decoder, logger
 
 		txe, err := executor.Execute(txEnv)
 		if err != nil {
+			ex := errors2.AsException(err)
 			logger.TraceMsg("Execution error",
 				structure.ErrorKey, err,
 				"tx_hash", txEnv.Tx.Hash())
 			return abciTypes.ResponseCheckTx{
-				Code: codes.EncodingErrorCode,
-				Log:  fmt.Sprintf("Could not execute transaction: %s, error: %v", txEnv, err),
+				Code: codes.TxExecutionErrorCode,
+				Log:  fmt.Sprintf("Could not execute transaction: %s, error: %v", txEnv, ex.Exception),
 			}
 		}
 
 		bs, err := txe.Receipt.Encode()
 		if err != nil {
 			return abciTypes.ResponseCheckTx{
-				Code: codes.TxExecutionErrorCode,
+				Code: codes.EncodingErrorCode,
 				Log:  fmt.Sprintf("Could not serialise receipt: %s", err),
 			}
 		}
@@ -207,11 +219,13 @@ func txExecutor(executor execution.BatchExecutor, txDecoder txs.Decoder, logger
 
 func (app *App) EndBlock(reqEndBlock abciTypes.RequestEndBlock) abciTypes.ResponseEndBlock {
 	var validatorUpdates abciTypes.Validators
-	app.blockchain.IterateValidators(func(id crypto.Addressable, power *big.Int) (stop bool) {
+	app.blockchain.PendingValidators().Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) {
+		app.logger.InfoMsg("Updating validator power", "validator_address", id.Address(),
+			"new_power", power)
 		validatorUpdates = append(validatorUpdates, abciTypes.Validator{
 			Address: id.Address().Bytes(),
 			PubKey:  id.PublicKey().ABCIPubKey(),
-			// Must be ensured during execution
+			// Must ensure power fits in an int64 during execution
 			Power: power.Int64(),
 		})
 		return
@@ -235,8 +249,8 @@ func (app *App) Commit() abciTypes.ResponseCommit {
 		"hash", app.block.Hash,
 		"txs", app.block.Header.NumTxs,
 		"block_time", blockTime,
-		"last_block_time", app.blockchain.Tip.LastBlockTime(),
-		"last_block_hash", app.blockchain.Tip.LastBlockHash())
+		"last_block_time", app.blockchain.LastBlockTime(),
+		"last_block_hash", app.blockchain.LastBlockHash())
 
 	// Lock the checker while we reset it and possibly while recheckTxs replays transactions
 	app.checker.Lock()
diff --git a/consensus/tendermint/config.go b/consensus/tendermint/config.go
index 46e391d0..d736e4ba 100644
--- a/consensus/tendermint/config.go
+++ b/consensus/tendermint/config.go
@@ -13,14 +13,16 @@ type BurrowTendermintConfig struct {
 	// Peers to which we automatically connect
 	PersistentPeers string
 	ListenAddress   string
+	// Optional external that nodes my provide with their NodeInfo
+	ExternalAddress string
 	Moniker         string
 	TendermintRoot  string
 }
 
 func DefaultBurrowTendermintConfig() *BurrowTendermintConfig {
-	tmDefaultConfig := tm_config.DefaultConfig()
+	//tmDefaultConfig := tm_config.DefaultConfig()
 	return &BurrowTendermintConfig{
-		ListenAddress:  tmDefaultConfig.P2P.ListenAddress,
+		ListenAddress:  "tcp://127.0.0.1:26656", //stmDefaultConfig.P2P.ListenAddress,
 		TendermintRoot: ".burrow",
 	}
 }
@@ -37,6 +39,7 @@ func (btc *BurrowTendermintConfig) TendermintConfig() *tm_config.Config {
 		conf.P2P.Seeds = btc.Seeds
 		conf.P2P.PersistentPeers = btc.PersistentPeers
 		conf.P2P.ListenAddress = btc.ListenAddress
+		conf.P2P.ExternalAddress = btc.ListenAddress
 		conf.Moniker = btc.Moniker
 		// Unfortunately this stops metrics from being used at all
 		conf.Instrumentation.Prometheus = false
diff --git a/consensus/tendermint/query/node_view.go b/consensus/tendermint/node_view.go
similarity index 86%
rename from consensus/tendermint/query/node_view.go
rename to consensus/tendermint/node_view.go
index 4c547bc2..62a50085 100644
--- a/consensus/tendermint/query/node_view.go
+++ b/consensus/tendermint/node_view.go
@@ -1,26 +1,24 @@
-package query
+package tendermint
 
 import (
 	"fmt"
 
-	"github.com/hyperledger/burrow/consensus/tendermint"
 	"github.com/hyperledger/burrow/crypto"
-	tm_crypto "github.com/tendermint/tendermint/crypto"
-
 	"github.com/hyperledger/burrow/txs"
 	"github.com/tendermint/tendermint/consensus"
 	ctypes "github.com/tendermint/tendermint/consensus/types"
+	tmCrypto "github.com/tendermint/tendermint/crypto"
 	"github.com/tendermint/tendermint/p2p"
 	"github.com/tendermint/tendermint/state"
 	"github.com/tendermint/tendermint/types"
 )
 
 type NodeView struct {
-	tmNode    *tendermint.Node
+	tmNode    *Node
 	txDecoder txs.Decoder
 }
 
-func NewNodeView(tmNode *tendermint.Node, txDecoder txs.Decoder) *NodeView {
+func NewNodeView(tmNode *Node, txDecoder txs.Decoder) *NodeView {
 	return &NodeView{
 		tmNode:    tmNode,
 		txDecoder: txDecoder,
@@ -28,7 +26,7 @@ func NewNodeView(tmNode *tendermint.Node, txDecoder txs.Decoder) *NodeView {
 }
 
 func (nv *NodeView) PrivValidatorPublicKey() (crypto.PublicKey, error) {
-	pub := nv.tmNode.PrivValidator().GetPubKey().(tm_crypto.PubKeyEd25519)
+	pub := nv.tmNode.PrivValidator().GetPubKey().(tmCrypto.PubKeyEd25519)
 
 	return crypto.PublicKeyFromBytes(pub[:], crypto.CurveTypeEd25519)
 }
diff --git a/consensus/tendermint/validator/priv_validator_memory.go b/consensus/tendermint/priv_validator_memory.go
similarity index 98%
rename from consensus/tendermint/validator/priv_validator_memory.go
rename to consensus/tendermint/priv_validator_memory.go
index 5159e503..fb63b76a 100644
--- a/consensus/tendermint/validator/priv_validator_memory.go
+++ b/consensus/tendermint/priv_validator_memory.go
@@ -1,4 +1,4 @@
-package validator
+package tendermint
 
 import (
 	"github.com/hyperledger/burrow/crypto"
diff --git a/consensus/tendermint/validator/sign_info.go b/consensus/tendermint/sign_info.go
similarity index 99%
rename from consensus/tendermint/validator/sign_info.go
rename to consensus/tendermint/sign_info.go
index 40230651..1a11cbf7 100644
--- a/consensus/tendermint/validator/sign_info.go
+++ b/consensus/tendermint/sign_info.go
@@ -1,4 +1,4 @@
-package validator
+package tendermint
 
 import (
 	"bytes"
diff --git a/consensus/tendermint/tendermint.go b/consensus/tendermint/tendermint.go
index 31f0c8cf..0122f580 100644
--- a/consensus/tendermint/tendermint.go
+++ b/consensus/tendermint/tendermint.go
@@ -4,13 +4,10 @@ import (
 	"os"
 	"path"
 
-	bcm "github.com/hyperledger/burrow/blockchain"
 	"github.com/hyperledger/burrow/consensus/tendermint/abci"
-	"github.com/hyperledger/burrow/execution"
 	"github.com/hyperledger/burrow/genesis"
 	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/logging/structure"
-	"github.com/hyperledger/burrow/txs"
 	"github.com/tendermint/tendermint/config"
 	tmCrypto "github.com/tendermint/tendermint/crypto"
 	dbm "github.com/tendermint/tendermint/libs/db"
@@ -45,8 +42,7 @@ func (n *Node) Close() {
 }
 
 func NewNode(conf *config.Config, privValidator tmTypes.PrivValidator, genesisDoc *tmTypes.GenesisDoc,
-	blockchain *bcm.Blockchain, checker execution.BatchExecutor, committer execution.BatchCommitter,
-	txDecoder txs.Decoder, metricsProvider node.MetricsProvider, panicFunc func(error), logger *logging.Logger) (*Node, error) {
+	app *abci.App, metricsProvider node.MetricsProvider, logger *logging.Logger) (*Node, error) {
 
 	var err error
 	// disable Tendermint's RPC
@@ -58,8 +54,6 @@ func NewNode(conf *config.Config, privValidator tmTypes.PrivValidator, genesisDo
 	}
 
 	nde := &Node{}
-	app := abci.NewApp(blockchain, checker, committer, txDecoder, panicFunc, logger)
-	conf.NodeKeyFile()
 	nde.Node, err = node.NewNode(conf, privValidator,
 		proxy.NewLocalClientCreator(app),
 		func() (*tmTypes.GenesisDoc, error) {
diff --git a/consensus/tendermint/validator/wire.go b/consensus/tendermint/wire.go
similarity index 89%
rename from consensus/tendermint/validator/wire.go
rename to consensus/tendermint/wire.go
index 3cdd4f0d..24f0bc11 100644
--- a/consensus/tendermint/validator/wire.go
+++ b/consensus/tendermint/wire.go
@@ -1,4 +1,4 @@
-package validator
+package tendermint
 
 import (
 	amino "github.com/tendermint/go-amino"
diff --git a/core/kernel.go b/core/kernel.go
index 72329f2d..46854844 100644
--- a/core/kernel.go
+++ b/core/kernel.go
@@ -27,9 +27,9 @@ import (
 	"time"
 
 	kitlog "github.com/go-kit/kit/log"
-	bcm "github.com/hyperledger/burrow/blockchain"
+	"github.com/hyperledger/burrow/bcm"
 	"github.com/hyperledger/burrow/consensus/tendermint"
-	"github.com/hyperledger/burrow/consensus/tendermint/query"
+	"github.com/hyperledger/burrow/consensus/tendermint/abci"
 	"github.com/hyperledger/burrow/event"
 	"github.com/hyperledger/burrow/execution"
 	"github.com/hyperledger/burrow/genesis"
@@ -51,10 +51,11 @@ import (
 )
 
 const (
-	CooldownMilliseconds              = 1000
-	ServerShutdownTimeoutMilliseconds = 1000
-	LoggingCallerDepth                = 5
-	AccountsRingMutexCount            = 100
+	FirstBlockTimeout      = 3 * time.Second
+	CooldownTime           = 1000 * time.Millisecond
+	ServerShutdownTimeout  = 1000 * time.Millisecond
+	LoggingCallerDepth     = 5
+	AccountsRingMutexCount = 100
 )
 
 // Kernel is the root structure of Burrow
@@ -64,8 +65,10 @@ type Kernel struct {
 	Service        *rpc.Service
 	Launchers      []process.Launcher
 	State          *execution.State
-	Blockchain     bcm.BlockchainInfo
+	Blockchain     *bcm.Blockchain
+	Node           *tendermint.Node
 	Logger         *logging.Logger
+	nodeInfo       string
 	processes      map[string]process.Process
 	shutdownNotify chan struct{}
 	shutdownOnce   sync.Once
@@ -75,57 +78,58 @@ func NewKernel(ctx context.Context, keyClient keys.KeyClient, privValidator tmTy
 	genesisDoc *genesis.GenesisDoc, tmConf *tmConfig.Config, rpcConfig *rpc.RPCConfig, keyConfig *keys.KeysConfig,
 	keyStore *keys.KeyStore, exeOptions []execution.ExecutionOption, logger *logging.Logger) (*Kernel, error) {
 
+	var err error
 	kern := &Kernel{
 		processes:      make(map[string]process.Process),
 		shutdownNotify: make(chan struct{}),
 	}
 	logger = logger.WithScope("NewKernel()").With(structure.TimeKey, kitlog.DefaultTimestampUTC)
 	tmLogger := logger.With(structure.CallerKey, kitlog.Caller(LoggingCallerDepth+1))
-	logger = logger.WithInfo(structure.CallerKey, kitlog.Caller(LoggingCallerDepth))
+	kern.Logger = logger.WithInfo(structure.CallerKey, kitlog.Caller(LoggingCallerDepth))
 	stateDB := dbm.NewDB("burrow_state", dbm.GoLevelDBBackend, tmConf.DBDir())
 
-	blockchain, err := bcm.LoadOrNewBlockchain(stateDB, genesisDoc, logger)
+	kern.Blockchain, err = bcm.LoadOrNewBlockchain(stateDB, genesisDoc, kern.Logger)
 	if err != nil {
 		return nil, fmt.Errorf("error creating or loading blockchain state: %v", err)
 	}
 
-	var state *execution.State
 	// These should be in sync unless we are at the genesis block
-	if blockchain.LastBlockHeight() > 0 {
-		state, err = execution.LoadState(stateDB, blockchain.AppHashAfterLastBlock())
+	if kern.Blockchain.LastBlockHeight() > 0 {
+		kern.State, err = execution.LoadState(stateDB, kern.Blockchain.AppHashAfterLastBlock())
 		if err != nil {
 			return nil, fmt.Errorf("could not load persisted execution state at hash 0x%X: %v",
-				blockchain.AppHashAfterLastBlock(), err)
+				kern.Blockchain.AppHashAfterLastBlock(), err)
 		}
 	} else {
-		state, err = execution.MakeGenesisState(stateDB, genesisDoc)
+		kern.State, err = execution.MakeGenesisState(stateDB, genesisDoc)
 	}
 
 	txCodec := txs.NewAminoCodec()
 	tmGenesisDoc := tendermint.DeriveGenesisDoc(genesisDoc)
-	checker := execution.NewBatchChecker(state, blockchain, logger)
+	checker := execution.NewBatchChecker(kern.State, kern.Blockchain, kern.Logger)
 
-	emitter := event.NewEmitter(logger)
-	committer := execution.NewBatchCommitter(state, blockchain, emitter, logger, exeOptions...)
+	kern.Emitter = event.NewEmitter(kern.Logger)
+	committer := execution.NewBatchCommitter(kern.State, kern.Blockchain, kern.Emitter, kern.Logger, exeOptions...)
 
-	// We could use this to provide/register our own metrics (though this will register them with us). Unforunately
+	kern.nodeInfo = fmt.Sprintf("Burrow_%s_%X", genesisDoc.ChainID(), privValidator.GetAddress())
+	app := abci.NewApp(kern.nodeInfo, kern.Blockchain, checker, committer, txCodec, kern.Panic, logger)
+	// We could use this to provide/register our own metrics (though this will register them with us). Unfortunately
 	// Tendermint currently ignores the metrics passed unless its own server is turned on.
 	metricsProvider := node.DefaultMetricsProvider
-	tmNode, err := tendermint.NewNode(tmConf, privValidator, tmGenesisDoc, blockchain, checker, committer, txCodec,
-		metricsProvider, kern.Panic, tmLogger)
+	kern.Node, err = tendermint.NewNode(tmConf, privValidator, tmGenesisDoc, app, metricsProvider, tmLogger)
 	if err != nil {
 		return nil, err
 	}
 
-	transactor := execution.NewTransactor(blockchain.Tip, emitter, execution.NewAccounts(checker, keyClient, AccountsRingMutexCount),
-		tmNode.MempoolReactor().BroadcastTx, txCodec, logger)
+	transactor := execution.NewTransactor(kern.Blockchain, kern.Emitter, execution.NewAccounts(checker, keyClient, AccountsRingMutexCount),
+		kern.Node.MempoolReactor().BroadcastTx, txCodec, kern.Logger)
 
-	nameRegState := state
-	accountState := state
-	service := rpc.NewService(accountState, nameRegState, blockchain, transactor,
-		query.NewNodeView(tmNode, txCodec), logger)
+	nameRegState := kern.State
+	accountState := kern.State
+	nodeView := tendermint.NewNodeView(kern.Node, txCodec)
+	kern.Service = rpc.NewService(accountState, nameRegState, kern.Blockchain, nodeView, kern.Logger)
 
-	launchers := []process.Launcher{
+	kern.Launchers = []process.Launcher{
 		{
 			Name:    "Profiling Server",
 			Enabled: rpcConfig.Profiler.Enabled,
@@ -136,7 +140,7 @@ func NewKernel(ctx context.Context, keyClient keys.KeyClient, privValidator tmTy
 				go func() {
 					err := debugServer.ListenAndServe()
 					if err != nil {
-						logger.InfoMsg("Error from pprof debug server", structure.ErrorKey, err)
+						kern.Logger.InfoMsg("Error from pprof debug server", structure.ErrorKey, err)
 					}
 				}()
 				return debugServer, nil
@@ -157,22 +161,22 @@ func NewKernel(ctx context.Context, keyClient keys.KeyClient, privValidator tmTy
 			Name:    "Tendermint",
 			Enabled: true,
 			Launch: func() (process.Process, error) {
-				err := tmNode.Start()
+				err := kern.Node.Start()
 				if err != nil {
 					return nil, fmt.Errorf("error starting Tendermint node: %v", err)
 				}
 				return process.ShutdownFunc(func(ctx context.Context) error {
-					err := tmNode.Stop()
+					err := kern.Node.Stop()
 					// Close tendermint database connections using our wrapper
-					defer tmNode.Close()
+					defer kern.Node.Close()
 					if err != nil {
 						return err
 					}
 					select {
 					case <-ctx.Done():
 						return ctx.Err()
-					case <-tmNode.Quit():
-						logger.InfoMsg("Tendermint Node has quit, closing DB connections...")
+					case <-kern.Node.Quit():
+						kern.Logger.InfoMsg("Tendermint Node has quit, closing DB connections...")
 						return nil
 					}
 					return err
@@ -183,7 +187,7 @@ func NewKernel(ctx context.Context, keyClient keys.KeyClient, privValidator tmTy
 			Name:    "RPC/tm",
 			Enabled: rpcConfig.TM.Enabled,
 			Launch: func() (process.Process, error) {
-				server, err := tm.StartServer(service, "/websocket", rpcConfig.TM.ListenAddress, logger)
+				server, err := tm.StartServer(kern.Service, "/websocket", rpcConfig.TM.ListenAddress, kern.Logger)
 				if err != nil {
 					return nil, err
 				}
@@ -194,7 +198,8 @@ func NewKernel(ctx context.Context, keyClient keys.KeyClient, privValidator tmTy
 			Name:    "RPC/metrics",
 			Enabled: rpcConfig.Metrics.Enabled,
 			Launch: func() (process.Process, error) {
-				server, err := metrics.StartServer(service, rpcConfig.Metrics.MetricsPath, rpcConfig.Metrics.ListenAddress, rpcConfig.Metrics.BlockSampleSize, logger)
+				server, err := metrics.StartServer(kern.Service, rpcConfig.Metrics.MetricsPath,
+					rpcConfig.Metrics.ListenAddress, rpcConfig.Metrics.BlockSampleSize, kern.Logger)
 				if err != nil {
 					return nil, err
 				}
@@ -210,7 +215,7 @@ func NewKernel(ctx context.Context, keyClient keys.KeyClient, privValidator tmTy
 					return nil, err
 				}
 
-				grpcServer := rpc.NewGRPCServer(logger)
+				grpcServer := rpc.NewGRPCServer(kern.Logger)
 				var ks *keys.KeyStore
 				if keyStore != nil {
 					ks = keyStore
@@ -218,17 +223,18 @@ func NewKernel(ctx context.Context, keyClient keys.KeyClient, privValidator tmTy
 
 				if keyConfig.GRPCServiceEnabled {
 					if keyStore == nil {
-						ks = keys.NewKeyStore(keyConfig.KeysDirectory, keyConfig.AllowBadFilePermissions, logger)
+						ks = keys.NewKeyStore(keyConfig.KeysDirectory, keyConfig.AllowBadFilePermissions, kern.Logger)
 					}
 					keys.RegisterKeysServer(grpcServer, ks)
 				}
 
-				rpcquery.RegisterQueryServer(grpcServer, rpcquery.NewQueryServer(state, nameRegState))
+				rpcquery.RegisterQueryServer(grpcServer, rpcquery.NewQueryServer(kern.State, nameRegState,
+					kern.Blockchain, nodeView, kern.Logger))
 
 				rpctransact.RegisterTransactServer(grpcServer, rpctransact.NewTransactServer(transactor, txCodec))
 
-				rpcevents.RegisterExecutionEventsServer(grpcServer, rpcevents.NewExecutionEventsServer(state, emitter,
-					blockchain.Tip, logger))
+				rpcevents.RegisterExecutionEventsServer(grpcServer, rpcevents.NewExecutionEventsServer(kern.State,
+					kern.Emitter, kern.Blockchain, kern.Logger))
 
 				// Provides metadata about services registered
 				//reflection.Register(grpcServer)
@@ -244,12 +250,6 @@ func NewKernel(ctx context.Context, keyClient keys.KeyClient, privValidator tmTy
 		},
 	}
 
-	kern.Emitter = emitter
-	kern.Service = service
-	kern.Launchers = launchers
-	kern.State = state
-	kern.Blockchain = blockchain
-	kern.Logger = logger
 	return kern, nil
 }
 
@@ -270,7 +270,7 @@ func (kern *Kernel) Boot() error {
 }
 
 func (kern *Kernel) Panic(err error) {
-	fmt.Fprintf(os.Stderr, "Kernel shutting down due to panic: %v", err)
+	fmt.Fprintf(os.Stderr, "%s: Kernel shutting down due to panic: %v", kern.nodeInfo, err)
 	kern.Shutdown(context.Background())
 	os.Exit(1)
 }
@@ -298,7 +298,7 @@ func (kern *Kernel) Shutdown(ctx context.Context) (err error) {
 		logger := kern.Logger.WithScope("Shutdown")
 		logger.InfoMsg("Attempting graceful shutdown...")
 		logger.InfoMsg("Shutting down servers")
-		ctx, cancel := context.WithTimeout(ctx, ServerShutdownTimeoutMilliseconds*time.Millisecond)
+		ctx, cancel := context.WithTimeout(ctx, ServerShutdownTimeout)
 		defer cancel()
 		// Shutdown servers in reverse order to boot
 		for i := len(kern.Launchers) - 1; i >= 0; i-- {
@@ -322,7 +322,7 @@ func (kern *Kernel) Shutdown(ctx context.Context) (err error) {
 		structure.Sync(kern.Logger.Trace)
 		// We don't want to wait for them, but yielding for a cooldown Let other goroutines flush
 		// potentially interesting final output (e.g. log messages)
-		time.Sleep(time.Millisecond * CooldownMilliseconds)
+		time.Sleep(CooldownTime)
 		close(kern.shutdownNotify)
 	})
 	return
diff --git a/crypto/public_key.go b/crypto/public_key.go
index 4d5764ad..27d59202 100644
--- a/crypto/public_key.go
+++ b/crypto/public_key.go
@@ -7,6 +7,7 @@ import (
 
 	"github.com/btcsuite/btcd/btcec"
 	abci "github.com/tendermint/tendermint/abci/types"
+	tmCrypto "github.com/tendermint/tendermint/crypto"
 	"github.com/tendermint/tendermint/crypto/tmhash"
 	"github.com/tmthrgd/go-hex"
 	"golang.org/x/crypto/ed25519"
@@ -136,6 +137,17 @@ func (p PublicKey) ABCIPubKey() abci.PubKey {
 	}
 }
 
+func PublicKeyFromTendermintPubKey(pubKey tmCrypto.PubKey) (PublicKey, error) {
+	switch pk := pubKey.(type) {
+	case tmCrypto.PubKeyEd25519:
+		return PublicKeyFromBytes(pk[:], CurveTypeEd25519)
+	case tmCrypto.PubKeySecp256k1:
+		return PublicKeyFromBytes(pk[:], CurveTypeSecp256k1)
+	default:
+		return PublicKey{}, fmt.Errorf("unrecognised tendermint public key type: %v", pk)
+	}
+
+}
 func PublicKeyFromABCIPubKey(pubKey abci.PubKey) (PublicKey, error) {
 	switch pubKey.Type {
 	case CurveTypeEd25519.ABCIType():
diff --git a/execution/contexts/call_context.go b/execution/contexts/call_context.go
index 5278b21c..fcf7e146 100644
--- a/execution/contexts/call_context.go
+++ b/execution/contexts/call_context.go
@@ -5,8 +5,8 @@ import (
 
 	"github.com/hyperledger/burrow/acm"
 	"github.com/hyperledger/burrow/acm/state"
+	"github.com/hyperledger/burrow/bcm"
 	"github.com/hyperledger/burrow/binary"
-	"github.com/hyperledger/burrow/blockchain"
 	"github.com/hyperledger/burrow/execution/errors"
 	"github.com/hyperledger/burrow/execution/evm"
 	"github.com/hyperledger/burrow/execution/exec"
@@ -19,7 +19,7 @@ import (
 const GasLimit = uint64(1000000)
 
 type CallContext struct {
-	Tip         blockchain.TipInfo
+	Tip         bcm.BlockchainInfo
 	StateWriter state.ReaderWriter
 	RunCall     bool
 	VMOptions   []func(*evm.VM)
@@ -101,7 +101,7 @@ func (ctx *CallContext) Precheck() (*acm.MutableAccount, acm.Account, error) {
 			return nil, nil, 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)", ctx.tx.Address)
+				"type (eg. PermsTx, NameTx)", ctx.tx.Address)
 		}
 
 		// Output account may be nil if we are still in mempool and contract was created in same block as this tx
diff --git a/execution/contexts/governance_context.go b/execution/contexts/governance_context.go
index dd0a8afe..39457b82 100644
--- a/execution/contexts/governance_context.go
+++ b/execution/contexts/governance_context.go
@@ -6,7 +6,7 @@ import (
 
 	"github.com/hyperledger/burrow/acm"
 	"github.com/hyperledger/burrow/acm/state"
-	"github.com/hyperledger/burrow/blockchain"
+	"github.com/hyperledger/burrow/acm/validator"
 	"github.com/hyperledger/burrow/execution/errors"
 	"github.com/hyperledger/burrow/execution/exec"
 	"github.com/hyperledger/burrow/genesis/spec"
@@ -17,18 +17,18 @@ import (
 
 type GovernanceContext struct {
 	StateWriter  state.ReaderWriter
-	ValidatorSet blockchain.ValidatorSet
+	ValidatorSet validator.Writer
 	Logger       *logging.Logger
-	tx           *payload.GovernanceTx
+	tx           *payload.GovTx
 	txe          *exec.TxExecution
 }
 
-// GovernanceTx provides a set of TemplateAccounts and GovernanceContext tries to alter the chain state to match the
+// GovTx provides a set of TemplateAccounts and GovernanceContext tries to alter the chain state to match the
 // specification given
 func (ctx *GovernanceContext) Execute(txe *exec.TxExecution) error {
 	var ok bool
 	ctx.txe = txe
-	ctx.tx, ok = txe.Envelope.Tx.Payload.(*payload.GovernanceTx)
+	ctx.tx, ok = txe.Envelope.Tx.Payload.(*payload.GovTx)
 	if !ok {
 		return fmt.Errorf("payload must be NameTx, but is: %v", txe.Envelope.Tx.Payload)
 	}
@@ -38,8 +38,9 @@ func (ctx *GovernanceContext) Execute(txe *exec.TxExecution) error {
 	}
 
 	// ensure all inputs have root permissions
-	if !allHavePermission(ctx.StateWriter, permission.Root, accounts, ctx.Logger) {
-		return fmt.Errorf("at least one input lacks Root permission needed for GovernanceTx")
+	err = allHavePermission(ctx.StateWriter, permission.Root, accounts, ctx.Logger)
+	if err != nil {
+		return errors.Wrap(err, "at least one input lacks permission for GovTx")
 	}
 
 	for _, i := range ctx.tx.Inputs {
@@ -49,28 +50,25 @@ func (ctx *GovernanceContext) Execute(txe *exec.TxExecution) error {
 	for _, update := range ctx.tx.AccountUpdates {
 		if update.Address == nil && update.PublicKey == nil {
 			// We do not want to generate a key
-			return fmt.Errorf("could not execution GovernanceTx since account template %v contains neither "+
+			return fmt.Errorf("could not execution GovTx since account template %v contains neither "+
 				"address or public key", update)
 		}
 		if update.PublicKey != nil {
 			address := update.PublicKey.Address()
 			if update.Address != nil && address != *update.Address {
 				return fmt.Errorf("supplied public key %v whose address %v does not match %v provided by"+
-					"GovernanceTx", update.PublicKey, address, update.Address)
+					"GovTx", update.PublicKey, address, update.Address)
 			}
 			update.Address = &address
 		}
-		if update.PublicKey == nil && update.Power != nil {
+		if update.PublicKey == nil && update.Balances().HasPower() {
 			// If we are updating power we will need the key
-			return fmt.Errorf("GovernanceTx must be provided with public key when updating validator power")
+			return fmt.Errorf("GovTx must be provided with public key when updating validator power")
 		}
-		account, err := state.GetMutableAccount(ctx.StateWriter, *update.Address)
+		account, err := getOrMakeOutput(ctx.StateWriter, accounts, *update.Address, ctx.Logger)
 		if err != nil {
 			return err
 		}
-		if account == nil {
-			return fmt.Errorf("account %v not found so cannot update using template %v", update.Address, update)
-		}
 		governAccountEvent, err := ctx.updateAccount(account, update)
 		if err != nil {
 			txe.GovernAccount(governAccountEvent, errors.AsException(err))
@@ -85,8 +83,8 @@ func (ctx *GovernanceContext) updateAccount(account *acm.MutableAccount, update
 	ev = &exec.GovernAccountEvent{
 		AccountUpdate: update,
 	}
-	if update.Amount != nil {
-		err = account.SetBalance(*update.Amount)
+	if update.Balances().HasNative() {
+		err = account.SetBalance(update.Balances().GetNative(0))
 		if err != nil {
 			return
 		}
@@ -95,13 +93,13 @@ func (ctx *GovernanceContext) updateAccount(account *acm.MutableAccount, update
 		// TODO: can we do something useful if provided with a NodeAddress for an account about to become a validator
 		// like add it to persistent peers or pre gossip so it gets inbound connections? If so under which circumstances?
 	}
-	if update.Power != nil {
+	if update.Balances().HasPower() {
 		if update.PublicKey == nil {
 			err = fmt.Errorf("updateAccount should have PublicKey by this point but appears not to for "+
 				"template account: %v", update)
 			return
 		}
-		power := new(big.Int).SetUint64(*update.Power)
+		power := new(big.Int).SetUint64(update.Balances().GetPower(0))
 		if !power.IsInt64() {
 			err = fmt.Errorf("power supplied in update to validator power for %v does not fit into int64 and "+
 				"so is not supported by Tendermint", update.Address)
diff --git a/execution/contexts/name_context.go b/execution/contexts/name_context.go
index b5ba18a8..10c37a15 100644
--- a/execution/contexts/name_context.go
+++ b/execution/contexts/name_context.go
@@ -6,7 +6,7 @@ import (
 	"regexp"
 
 	"github.com/hyperledger/burrow/acm/state"
-	"github.com/hyperledger/burrow/blockchain"
+	"github.com/hyperledger/burrow/bcm"
 	"github.com/hyperledger/burrow/execution/errors"
 	"github.com/hyperledger/burrow/execution/exec"
 	"github.com/hyperledger/burrow/execution/names"
@@ -21,7 +21,7 @@ var regexpAlphaNum = regexp.MustCompile("^[a-zA-Z0-9._/-@]*$")
 var regexpJSON = regexp.MustCompile(`^[a-zA-Z0-9_/ \-+"':,\n\t.{}()\[\]]*$`)
 
 type NameContext struct {
-	Tip         blockchain.TipInfo
+	Tip         bcm.BlockchainInfo
 	StateWriter state.ReaderWriter
 	NameReg     names.ReaderWriter
 	Logger      *logging.Logger
diff --git a/execution/contexts/permissions_context.go b/execution/contexts/permissions_context.go
index 4572e41c..00cbd1a5 100644
--- a/execution/contexts/permissions_context.go
+++ b/execution/contexts/permissions_context.go
@@ -5,7 +5,7 @@ import (
 
 	"github.com/hyperledger/burrow/acm"
 	"github.com/hyperledger/burrow/acm/state"
-	"github.com/hyperledger/burrow/blockchain"
+	"github.com/hyperledger/burrow/bcm"
 	"github.com/hyperledger/burrow/crypto"
 	"github.com/hyperledger/burrow/execution/errors"
 	"github.com/hyperledger/burrow/execution/exec"
@@ -16,17 +16,17 @@ import (
 )
 
 type PermissionsContext struct {
-	Tip         blockchain.TipInfo
+	Tip         bcm.BlockchainInfo
 	StateWriter state.ReaderWriter
 	Logger      *logging.Logger
-	tx          *payload.PermissionsTx
+	tx          *payload.PermsTx
 }
 
 func (ctx *PermissionsContext) Execute(txe *exec.TxExecution) error {
 	var ok bool
-	ctx.tx, ok = txe.Envelope.Tx.Payload.(*payload.PermissionsTx)
+	ctx.tx, ok = txe.Envelope.Tx.Payload.(*payload.PermsTx)
 	if !ok {
-		return fmt.Errorf("payload must be PermissionsTx, but is: %v", txe.Envelope.Tx.Payload)
+		return fmt.Errorf("payload must be PermsTx, but is: %v", txe.Envelope.Tx.Payload)
 	}
 	// Validate input
 	inAcc, err := state.GetMutableAccount(ctx.StateWriter, ctx.tx.Input.Address)
@@ -41,7 +41,7 @@ func (ctx *PermissionsContext) Execute(txe *exec.TxExecution) error {
 
 	err = ctx.tx.PermArgs.EnsureValid()
 	if err != nil {
-		return fmt.Errorf("PermissionsTx received containing invalid PermArgs: %v", err)
+		return fmt.Errorf("PermsTx received containing invalid PermArgs: %v", err)
 	}
 
 	permFlag := ctx.tx.PermArgs.PermFlag
@@ -61,7 +61,7 @@ func (ctx *PermissionsContext) Execute(txe *exec.TxExecution) error {
 
 	value := ctx.tx.Input.Amount
 
-	ctx.Logger.TraceMsg("New PermissionsTx",
+	ctx.Logger.TraceMsg("New PermsTx",
 		"perm_args", ctx.tx.PermArgs.String())
 
 	var permAcc acm.Account
@@ -114,7 +114,7 @@ func (ctx *PermissionsContext) Execute(txe *exec.TxExecution) error {
 	}
 
 	// Good!
-	ctx.Logger.TraceMsg("Incrementing sequence number for PermissionsTx",
+	ctx.Logger.TraceMsg("Incrementing sequence number for PermsTx",
 		"tag", "sequence",
 		"account", inAcc.Address(),
 		"old_sequence", inAcc.Sequence(),
diff --git a/execution/contexts/send_context.go b/execution/contexts/send_context.go
index 592cb6c4..a50c0b88 100644
--- a/execution/contexts/send_context.go
+++ b/execution/contexts/send_context.go
@@ -4,7 +4,7 @@ import (
 	"fmt"
 
 	"github.com/hyperledger/burrow/acm/state"
-	"github.com/hyperledger/burrow/blockchain"
+	"github.com/hyperledger/burrow/bcm"
 	"github.com/hyperledger/burrow/execution/errors"
 	"github.com/hyperledger/burrow/execution/exec"
 	"github.com/hyperledger/burrow/logging"
@@ -13,7 +13,7 @@ import (
 )
 
 type SendContext struct {
-	Tip         blockchain.TipInfo
+	Tip         bcm.BlockchainInfo
 	StateWriter state.ReaderWriter
 	Logger      *logging.Logger
 	tx          *payload.SendTx
@@ -31,8 +31,9 @@ func (ctx *SendContext) Execute(txe *exec.TxExecution) error {
 	}
 
 	// ensure all inputs have send permissions
-	if !allHavePermission(ctx.StateWriter, permission.Send, accounts, ctx.Logger) {
-		return fmt.Errorf("at least one input lacks permission for SendTx")
+	err = allHavePermission(ctx.StateWriter, permission.Send, accounts, ctx.Logger)
+	if err != nil {
+		return errors.Wrap(err, "at least one input lacks permission for SendTx")
 	}
 
 	// add outputs to accounts map
diff --git a/execution/contexts/shared.go b/execution/contexts/shared.go
index ed97bbd1..23f645f6 100644
--- a/execution/contexts/shared.go
+++ b/execution/contexts/shared.go
@@ -43,38 +43,45 @@ func getOrMakeOutputs(accountGetter state.AccountGetter, accs map[crypto.Address
 	if accs == nil {
 		accs = make(map[crypto.Address]*acm.MutableAccount)
 	}
-
 	// we should err if an account is being created but the inputs don't have permission
-	var checkedCreatePerms bool
+	var err error
 	for _, out := range outs {
-		// Account shouldn't be duplicated
-		if _, ok := accs[out.Address]; ok {
-			return nil, errors.ErrorCodeDuplicateAddress
-		}
-		acc, err := state.GetMutableAccount(accountGetter, out.Address)
+		accs[out.Address], err = getOrMakeOutput(accountGetter, accs, out.Address, logger)
 		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
 }
 
+func getOrMakeOutput(accountGetter state.AccountGetter, accs map[crypto.Address]*acm.MutableAccount,
+	outputAddress crypto.Address, logger *logging.Logger) (*acm.MutableAccount, error) {
+
+	// Account shouldn't be duplicated
+	if _, ok := accs[outputAddress]; ok {
+		return nil, errors.ErrorCodeDuplicateAddress
+	}
+	acc, err := state.GetMutableAccount(accountGetter, outputAddress)
+	if err != nil {
+		return nil, err
+	}
+	// output account may be nil (new)
+	if acc == nil {
+		if !hasCreateAccountPermission(accountGetter, accs, logger) {
+			return nil, fmt.Errorf("at least one input does not have permission to create accounts")
+		}
+		logger.InfoMsg("Account not found so attempting to create it", "address", outputAddress)
+		acc = acm.ConcreteAccount{
+			Address:     outputAddress,
+			Sequence:    0,
+			Balance:     0,
+			Permissions: permission.ZeroAccountPermissions,
+		}.MutableAccount()
+	}
+
+	return acc, nil
+}
+
 func validateInputs(accs map[crypto.Address]*acm.MutableAccount, ins []*payload.TxInput) (uint64, error) {
 	total := uint64(0)
 	for _, in := range ins {
@@ -188,15 +195,17 @@ func HasPermission(accountGetter state.AccountGetter, acc acm.Account, perm perm
 	return v
 }
 
-// TODO: for debug log the failed accounts
 func allHavePermission(accountGetter state.AccountGetter, perm permission.PermFlag,
-	accs map[crypto.Address]*acm.MutableAccount, logger *logging.Logger) bool {
+	accs map[crypto.Address]*acm.MutableAccount, logger *logging.Logger) error {
 	for _, acc := range accs {
 		if !HasPermission(accountGetter, acc, perm, logger) {
-			return false
+			return errors.PermissionDenied{
+				Address: acc.Address(),
+				Perm:    perm,
+			}
 		}
 	}
-	return true
+	return nil
 }
 
 func hasNamePermission(accountGetter state.AccountGetter, acc acm.Account,
diff --git a/execution/errors/errors.go b/execution/errors/errors.go
index b3bc5541..00e49c47 100644
--- a/execution/errors/errors.go
+++ b/execution/errors/errors.go
@@ -44,6 +44,10 @@ func (c Code) ErrorCode() Code {
 	return c
 }
 
+func (c Code) Uint32() uint32 {
+	return uint32(c)
+}
+
 func (c Code) Error() string {
 	return fmt.Sprintf("Error %d: %s", c, c.String())
 }
@@ -76,6 +80,8 @@ func (c Code) String() string {
 		return "Data stack underflow"
 	case ErrorCodeInvalidContract:
 		return "Invalid contract"
+	case ErrorCodePermissionDenied:
+		return "Permission denied"
 	case ErrorCodeNativeContractCodeCopy:
 		return "Tried to copy native contract code"
 	case ErrorCodeExecutionAborted:
@@ -134,8 +140,9 @@ func AsException(err error) *Exception {
 	}
 }
 
-func Wrap(err CodedError, message string) *Exception {
-	return NewCodedError(err.ErrorCode(), message+": "+err.Error())
+func Wrap(err error, message string) *Exception {
+	ex := AsException(err)
+	return NewCodedError(ex.ErrorCode(), message+": "+ex.Error())
 }
 
 func Errorf(format string, a ...interface{}) *Exception {
diff --git a/execution/errors/errors_test.go b/execution/errors/errors_test.go
index 33d487b4..c80c0572 100644
--- a/execution/errors/errors_test.go
+++ b/execution/errors/errors_test.go
@@ -5,8 +5,6 @@ import (
 	"fmt"
 	"testing"
 
-	"fmt"
-
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 )
diff --git a/execution/errors/vm.go b/execution/errors/vm.go
index 7e97d375..95b36cca 100644
--- a/execution/errors/vm.go
+++ b/execution/errors/vm.go
@@ -9,7 +9,8 @@ import (
 )
 
 type PermissionDenied struct {
-	Perm permission.PermFlag
+	Address crypto.Address
+	Perm    permission.PermFlag
 }
 
 func (err PermissionDenied) ErrorCode() Code {
@@ -17,7 +18,7 @@ func (err PermissionDenied) ErrorCode() Code {
 }
 
 func (err PermissionDenied) Error() string {
-	return fmt.Sprintf("Contract does not have permission to %v", err.Perm)
+	return fmt.Sprintf("Account/contract %v does not have permission %v", err.Address, err.Perm)
 }
 
 type NestedCall struct {
diff --git a/execution/evm/vm.go b/execution/evm/vm.go
index 53d9b1eb..0182a3f5 100644
--- a/execution/evm/vm.go
+++ b/execution/evm/vm.go
@@ -855,7 +855,10 @@ func (vm *VM) call(callState *state.Cache, caller acm.Account, callee *acm.Mutab
 			vm.returnData = nil
 
 			if !HasPermission(callState, callee, permission.CreateContract) {
-				return nil, errors.PermissionDenied{Perm: permission.CreateContract}
+				return nil, errors.PermissionDenied{
+					Address: callee.Address(),
+					Perm:    permission.CreateContract,
+				}
 			}
 			contractValue, popErr := stack.PopU64()
 			if popErr != nil {
@@ -902,7 +905,10 @@ func (vm *VM) call(callState *state.Cache, caller acm.Account, callee *acm.Mutab
 			vm.returnData = nil
 
 			if !HasPermission(callState, callee, permission.Call) {
-				return nil, errors.PermissionDenied{Perm: permission.Call}
+				return nil, errors.PermissionDenied{
+					Address: callee.Address(),
+					Perm:    permission.Call,
+				}
 			}
 			gasLimit, popErr := stack.PopU64()
 			if popErr != nil {
@@ -982,7 +988,10 @@ func (vm *VM) call(callState *state.Cache, caller acm.Account, callee *acm.Mutab
 					// nil account means we're sending funds to a new account
 					if acc == nil {
 						if !HasPermission(callState, caller, permission.CreateAccount) {
-							return nil, errors.PermissionDenied{Perm: permission.CreateAccount}
+							return nil, errors.PermissionDenied{
+								Address: callee.Address(),
+								Perm:    permission.CreateAccount,
+							}
 						}
 						acc = acm.ConcreteAccount{Address: crypto.AddressFromWord256(addr)}.MutableAccount()
 					}
@@ -1077,7 +1086,10 @@ func (vm *VM) call(callState *state.Cache, caller acm.Account, callee *acm.Mutab
 					return nil, firstErr(err, gasErr)
 				}
 				if !HasPermission(callState, callee, permission.CreateContract) {
-					return nil, firstErr(err, errors.PermissionDenied{Perm: permission.CreateContract})
+					return nil, firstErr(err, errors.PermissionDenied{
+						Address: callee.Address(),
+						Perm:    permission.CreateContract,
+					})
 				}
 				var createErr errors.CodedError
 				receiver, createErr = vm.createAccount(callState, callee, logger)
diff --git a/execution/exec/exec.pb.go b/execution/exec/exec.pb.go
index 26108e09..df1d5e80 100644
--- a/execution/exec/exec.pb.go
+++ b/execution/exec/exec.pb.go
@@ -28,7 +28,6 @@ import golang_proto "github.com/golang/protobuf/proto"
 import fmt "fmt"
 import math "math"
 import _ "github.com/gogo/protobuf/gogoproto"
-import _ "github.com/tendermint/tendermint/abci/types"
 import errors "github.com/hyperledger/burrow/execution/errors"
 import names "github.com/hyperledger/burrow/execution/names"
 import txs "github.com/hyperledger/burrow/txs"
@@ -3351,68 +3350,67 @@ func init() { proto.RegisterFile("exec.proto", fileDescriptorExec) }
 func init() { golang_proto.RegisterFile("exec.proto", fileDescriptorExec) }
 
 var fileDescriptorExec = []byte{
-	// 999 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x4f, 0x6f, 0x1b, 0x45,
-	0x14, 0xef, 0xda, 0xeb, 0x7f, 0xcf, 0x76, 0x09, 0xa3, 0x80, 0x56, 0x3d, 0xd8, 0xd6, 0x16, 0x55,
-	0x21, 0xb4, 0x6b, 0xe4, 0x12, 0x24, 0x40, 0x42, 0x8a, 0x89, 0x95, 0xa4, 0x0a, 0x09, 0x4c, 0x5d,
-	0x10, 0x08, 0x0e, 0xeb, 0xdd, 0xc1, 0x59, 0xd5, 0xde, 0x59, 0xcd, 0xce, 0x86, 0xf5, 0x87, 0xe0,
-	0xc6, 0xa1, 0xdc, 0xf8, 0x28, 0x1c, 0x73, 0x83, 0x0b, 0x97, 0x1e, 0x2c, 0x94, 0x7e, 0x04, 0x38,
-	0xf5, 0x84, 0xe6, 0xcf, 0xae, 0xd7, 0x02, 0x35, 0x55, 0x92, 0x8b, 0x35, 0xef, 0xbd, 0xdf, 0xfc,
-	0xe6, 0xcd, 0x7b, 0xbf, 0x37, 0x5e, 0x00, 0x92, 0x12, 0xcf, 0x89, 0x18, 0xe5, 0x14, 0x99, 0x62,
-	0x7d, 0xe7, 0xc1, 0x34, 0xe0, 0xa7, 0xc9, 0xc4, 0xf1, 0xe8, 0xbc, 0x3f, 0xa5, 0x53, 0xda, 0x97,
-	0xc1, 0x49, 0xf2, 0x83, 0xb4, 0xa4, 0x21, 0x57, 0x6a, 0xd3, 0x9d, 0xfb, 0x05, 0x38, 0x27, 0xa1,
-	0x4f, 0xd8, 0x3c, 0x08, 0x79, 0xdf, 0x9d, 0x78, 0x41, 0x9f, 0x2f, 0x22, 0x12, 0xab, 0x5f, 0x8d,
-	0x6e, 0x11, 0xc6, 0x28, 0xcb, 0xac, 0x66, 0xe8, 0xce, 0xf3, 0x50, 0x83, 0xa7, 0xd9, 0x72, 0x23,
-	0x12, 0x2c, 0x71, 0x1c, 0xd0, 0x50, 0x7b, 0x20, 0x8e, 0xb2, 0x34, 0xed, 0x9f, 0x0d, 0xb8, 0x3d,
-	0x9c, 0x51, 0xef, 0xe9, 0x28, 0x25, 0x5e, 0xc2, 0x03, 0x1a, 0xa2, 0xb7, 0xa1, 0x7a, 0x40, 0x82,
-	0xe9, 0x29, 0xb7, 0x8c, 0x9e, 0xb1, 0x65, 0x62, 0x6d, 0xa1, 0x87, 0xd0, 0x94, 0xc8, 0x03, 0xe2,
-	0xfa, 0x84, 0x59, 0xa5, 0x9e, 0xb1, 0xd5, 0x1c, 0xbc, 0xe9, 0xc8, 0x3b, 0x17, 0x02, 0xb8, 0x88,
-	0x42, 0x3b, 0xd0, 0x1a, 0xa7, 0x39, 0x77, 0x6c, 0x95, 0x7b, 0xe5, 0xd5, 0xae, 0x42, 0x04, 0xaf,
-	0xc1, 0xec, 0x8f, 0xd6, 0xce, 0x42, 0x08, 0xcc, 0x47, 0x8f, 0x4f, 0x8e, 0x65, 0x42, 0x0d, 0x2c,
-	0xd7, 0x22, 0xcd, 0xe3, 0x64, 0x3e, 0x4e, 0x63, 0x99, 0x49, 0x05, 0x6b, 0xcb, 0xfe, 0xb3, 0x0c,
-	0xcd, 0x02, 0x17, 0x7a, 0x04, 0xd5, 0x71, 0x3a, 0x5e, 0x44, 0x44, 0xe2, 0xda, 0xc3, 0xc1, 0xcb,
-	0x65, 0xd7, 0x29, 0xd4, 0xf9, 0x74, 0x11, 0x11, 0x36, 0x23, 0xfe, 0x94, 0xb0, 0xfe, 0x24, 0x61,
-	0x8c, 0xfe, 0xd8, 0xe7, 0x69, 0xdc, 0x8f, 0xdc, 0xc5, 0x8c, 0xba, 0xbe, 0x23, 0x76, 0x62, 0xcd,
-	0x80, 0x3e, 0x17, 0x5c, 0x07, 0x6e, 0x7c, 0x6a, 0x95, 0x7b, 0xc6, 0x56, 0x6b, 0xb8, 0x73, 0xbe,
-	0xec, 0xde, 0x7a, 0xbe, 0xec, 0x3e, 0x78, 0x35, 0xdf, 0x24, 0x08, 0x5d, 0xb6, 0x70, 0x0e, 0x48,
-	0x3a, 0x5c, 0x70, 0x12, 0x63, 0x4d, 0x52, 0xa8, 0xb4, 0xb9, 0x56, 0xe9, 0x4d, 0xa8, 0x1c, 0x86,
-	0x3e, 0x49, 0xad, 0x8a, 0x74, 0x2b, 0x03, 0x7d, 0x03, 0xf5, 0x51, 0x78, 0x46, 0x66, 0x34, 0x22,
-	0x56, 0x55, 0x16, 0xbf, 0xed, 0x88, 0x36, 0x67, 0xce, 0xa1, 0xf3, 0x7c, 0xd9, 0xdd, 0xbe, 0xf4,
-	0x66, 0x39, 0x1e, 0xe7, 0x74, 0xe8, 0x2e, 0x54, 0x47, 0x67, 0x24, 0xe4, 0xb1, 0x55, 0x93, 0xfd,
-	0x69, 0xaa, 0xfe, 0x48, 0x1f, 0xd6, 0x21, 0xf4, 0x0e, 0x54, 0x31, 0x89, 0x93, 0x19, 0xb7, 0xea,
-	0xf2, 0xf4, 0x96, 0x02, 0x29, 0x1f, 0xd6, 0x31, 0x74, 0x0f, 0x6a, 0x98, 0x78, 0x24, 0x88, 0xb8,
-	0xd5, 0xd0, 0x30, 0x71, 0xa8, 0xf6, 0xe1, 0x2c, 0x88, 0xfa, 0xd0, 0x18, 0xa5, 0x1e, 0x89, 0x44,
-	0x8f, 0x2c, 0xc8, 0xb4, 0xa4, 0x04, 0x9d, 0x07, 0xf0, 0x0a, 0x63, 0xff, 0x5e, 0x12, 0xd5, 0x92,
-	0x72, 0x58, 0xb5, 0xd4, 0xb8, 0xc1, 0x96, 0x96, 0x6e, 0xa2, 0xa5, 0xef, 0x41, 0x43, 0x96, 0x4b,
-	0x66, 0x57, 0x96, 0xd9, 0xb5, 0x5f, 0x2e, 0xbb, 0x2b, 0x27, 0x5e, 0x2d, 0x91, 0x05, 0x35, 0x69,
-	0x1c, 0xee, 0x49, 0x01, 0x34, 0x70, 0x66, 0x16, 0x94, 0x51, 0xf9, 0x7f, 0x65, 0x54, 0x8b, 0xca,
-	0x58, 0xab, 0x65, 0xed, 0xf2, 0x5a, 0x7e, 0x6c, 0x3e, 0xfb, 0xb5, 0x7b, 0xcb, 0xfe, 0xa9, 0x04,
-	0x15, 0x79, 0xa0, 0x68, 0xad, 0x9e, 0x6a, 0xa3, 0xd8, 0x5a, 0x3d, 0xd0, 0x59, 0xd9, 0xef, 0x89,
-	0xc3, 0xa3, 0x84, 0xeb, 0xd1, 0xdf, 0x50, 0x20, 0xe9, 0x52, 0x4a, 0x51, 0x61, 0xf4, 0x2e, 0x54,
-	0x4f, 0x12, 0x2e, 0x80, 0xe5, 0xe2, 0x1b, 0xa1, 0x7c, 0x5a, 0x53, 0xca, 0x40, 0x77, 0xc1, 0xfc,
-	0xcc, 0x9d, 0xcd, 0xe4, 0xf5, 0x9b, 0x83, 0x37, 0x14, 0x50, 0x78, 0x14, 0x4c, 0x06, 0x51, 0x0f,
-	0xca, 0x47, 0x74, 0x2a, 0x2b, 0xd1, 0x1c, 0xdc, 0x56, 0x98, 0x23, 0x3a, 0x55, 0x10, 0x11, 0x42,
-	0x9f, 0x42, 0x7b, 0x9f, 0x9e, 0x11, 0x16, 0xee, 0x7a, 0x1e, 0x4d, 0x42, 0xae, 0xe7, 0xc3, 0x52,
-	0xd8, 0xb5, 0x90, 0xda, 0xb5, 0x0e, 0xd7, 0xf5, 0x78, 0x66, 0x64, 0x0a, 0x17, 0xf5, 0xc7, 0x84,
-	0x27, 0x2c, 0x94, 0x05, 0x69, 0x61, 0x6d, 0x89, 0x8e, 0xed, 0xbb, 0xf1, 0x93, 0x98, 0xf8, 0xb2,
-	0x08, 0x26, 0xce, 0x4c, 0xb4, 0x0d, 0x8d, 0x63, 0x77, 0x4e, 0x46, 0x21, 0x67, 0x0b, 0x7d, 0xef,
-	0x96, 0xa3, 0x9e, 0x64, 0xe9, 0xc3, 0xab, 0x30, 0x7a, 0x1f, 0xea, 0x5f, 0x10, 0x36, 0xdf, 0x65,
-	0xd3, 0x58, 0xdf, 0x7c, 0xd3, 0x29, 0xbc, 0xd2, 0x59, 0x0c, 0xe7, 0x28, 0xfb, 0x6f, 0x03, 0xea,
-	0xd9, 0x95, 0xd1, 0x31, 0xd4, 0x76, 0x7d, 0x9f, 0x91, 0x38, 0x56, 0xd9, 0x0d, 0x3f, 0xd0, 0x9a,
-	0xbd, 0xff, 0x6a, 0xcd, 0x7a, 0x6c, 0x11, 0x71, 0xea, 0xe8, 0xbd, 0x38, 0x23, 0x41, 0x87, 0x60,
-	0xee, 0xb9, 0xdc, 0xbd, 0xde, 0x00, 0x48, 0x0a, 0x74, 0x04, 0xd5, 0x31, 0x8d, 0x02, 0x4f, 0x3d,
-	0xf4, 0xaf, 0x9d, 0x99, 0x26, 0xfb, 0x9a, 0x32, 0x7f, 0xb0, 0xf3, 0x21, 0xd6, 0x1c, 0xf6, 0x3f,
-	0x06, 0x34, 0x72, 0x31, 0xa0, 0x6d, 0xa8, 0x0b, 0x43, 0xa6, 0x6a, 0x14, 0xb5, 0x90, 0x79, 0x71,
-	0x1e, 0x17, 0x79, 0x9c, 0xb0, 0x60, 0x1a, 0x84, 0xfa, 0x52, 0x57, 0xab, 0x90, 0xe6, 0x40, 0x1d,
-	0x80, 0xc7, 0xdc, 0xf5, 0x9e, 0xee, 0x91, 0x88, 0xab, 0xa7, 0xdf, 0xc4, 0x05, 0x8f, 0x78, 0x43,
-	0xb4, 0x5a, 0xcc, 0x6b, 0xbd, 0x21, 0x8a, 0xc4, 0xfe, 0x12, 0xd0, 0x7f, 0x25, 0x8b, 0x3e, 0x81,
-	0xb6, 0xb6, 0x9f, 0x44, 0xbe, 0xcb, 0x89, 0xae, 0xc1, 0x5b, 0x8e, 0xfc, 0x37, 0x1f, 0x93, 0x79,
-	0x34, 0x73, 0x39, 0xd1, 0x10, 0xbc, 0x8e, 0xb5, 0xbf, 0x03, 0x58, 0xcd, 0xe9, 0x4d, 0x0b, 0xc8,
-	0xfe, 0x1e, 0x9a, 0x85, 0xe1, 0xbe, 0x71, 0xfa, 0x5f, 0x4a, 0xb0, 0xd6, 0x59, 0xb1, 0xd6, 0x4f,
-	0xd5, 0x95, 0x3b, 0xab, 0x38, 0x72, 0x36, 0x72, 0x3d, 0x9d, 0x28, 0x8e, 0x7c, 0x90, 0xca, 0xd7,
-	0x1f, 0xa4, 0x4d, 0xa8, 0x7c, 0xe5, 0xce, 0x12, 0xa2, 0xbf, 0x0c, 0x94, 0x81, 0x36, 0xa0, 0xbc,
-	0xef, 0xc6, 0xfa, 0x3f, 0x41, 0x2c, 0x87, 0xc3, 0xf3, 0x8b, 0x8e, 0xf1, 0xc7, 0x45, 0xc7, 0xf8,
-	0xeb, 0xa2, 0x63, 0xfc, 0xf6, 0xa2, 0x63, 0x9c, 0xbf, 0xe8, 0x18, 0xdf, 0x5e, 0x92, 0x3e, 0xc9,
-	0x3e, 0x8e, 0xe4, 0x6a, 0x52, 0x95, 0x9f, 0x82, 0x0f, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x47,
-	0x90, 0xbb, 0xef, 0xbf, 0x0a, 0x00, 0x00,
+	// 979 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x4f, 0x6f, 0xe3, 0x44,
+	0x14, 0x5f, 0x37, 0xce, 0xbf, 0x97, 0x64, 0x29, 0xa3, 0x82, 0xac, 0x3d, 0x24, 0x91, 0x17, 0xad,
+	0x4a, 0x61, 0x1d, 0x94, 0xa5, 0x48, 0x80, 0x84, 0xd4, 0xd0, 0xa8, 0xed, 0xaa, 0xb4, 0x30, 0x9b,
+	0x05, 0x81, 0xe0, 0xe0, 0x38, 0x83, 0x6b, 0xad, 0xe3, 0xb1, 0xc6, 0xe3, 0xe2, 0x7c, 0x08, 0x6e,
+	0x1c, 0x96, 0x1b, 0x1f, 0x85, 0x63, 0x6f, 0x70, 0xe1, 0xb2, 0x87, 0x08, 0x75, 0x3f, 0x02, 0x9c,
+	0xf6, 0x84, 0xe6, 0x8f, 0x1d, 0x47, 0xa0, 0x2d, 0xda, 0xf6, 0x36, 0xef, 0xbd, 0xdf, 0xfc, 0xe6,
+	0xcd, 0x7b, 0xbf, 0x37, 0x36, 0x00, 0xc9, 0x88, 0xe7, 0xc4, 0x8c, 0x72, 0x8a, 0x4c, 0xb1, 0xbe,
+	0x73, 0xdf, 0x0f, 0xf8, 0x59, 0x3a, 0x75, 0x3c, 0x3a, 0x1f, 0xf8, 0xd4, 0xa7, 0x03, 0x19, 0x9c,
+	0xa6, 0xdf, 0x4b, 0x4b, 0x1a, 0x72, 0xa5, 0x36, 0xdd, 0x69, 0x13, 0xc6, 0x28, 0x4b, 0xb4, 0xd5,
+	0x8a, 0xdc, 0x39, 0xc9, 0x8d, 0x26, 0xcf, 0xf2, 0xe5, 0x66, 0x4c, 0xd8, 0x3c, 0x48, 0x92, 0x80,
+	0x46, 0xda, 0x03, 0x49, 0x9c, 0x1f, 0x6c, 0xff, 0x64, 0xc0, 0xed, 0x51, 0x48, 0xbd, 0x27, 0xe3,
+	0x8c, 0x78, 0x29, 0x0f, 0x68, 0x84, 0xde, 0x84, 0xda, 0x21, 0x09, 0xfc, 0x33, 0x6e, 0x19, 0x7d,
+	0x63, 0xdb, 0xc4, 0xda, 0x42, 0x0f, 0xa0, 0x25, 0x91, 0x87, 0xc4, 0x9d, 0x11, 0x66, 0x6d, 0xf4,
+	0x8d, 0xed, 0xd6, 0xf0, 0x75, 0x47, 0xde, 0xa2, 0x14, 0xc0, 0x65, 0x14, 0xda, 0x85, 0xf6, 0x24,
+	0x2b, 0xb8, 0x13, 0xab, 0xd2, 0xaf, 0xac, 0x76, 0x95, 0x22, 0x78, 0x0d, 0x66, 0x7f, 0xb8, 0x76,
+	0x16, 0x42, 0x60, 0x3e, 0x7c, 0x74, 0x7a, 0x22, 0x13, 0x6a, 0x62, 0xb9, 0x16, 0x69, 0x9e, 0xa4,
+	0xf3, 0x49, 0x96, 0xc8, 0x4c, 0xaa, 0x58, 0x5b, 0xf6, 0x1f, 0x15, 0x68, 0x95, 0xb8, 0xd0, 0x43,
+	0xa8, 0x4d, 0xb2, 0xc9, 0x22, 0x26, 0x12, 0xd7, 0x19, 0x0d, 0x5f, 0x2c, 0x7b, 0x4e, 0xa9, 0xd0,
+	0x67, 0x8b, 0x98, 0xb0, 0x90, 0xcc, 0x7c, 0xc2, 0x06, 0xd3, 0x94, 0x31, 0xfa, 0xc3, 0x80, 0x67,
+	0xc9, 0x20, 0x76, 0x17, 0x21, 0x75, 0x67, 0x8e, 0xd8, 0x89, 0x35, 0x03, 0xfa, 0x4c, 0x70, 0x1d,
+	0xba, 0xc9, 0x99, 0x55, 0xe9, 0x1b, 0xdb, 0xed, 0xd1, 0xee, 0xc5, 0xb2, 0x77, 0xeb, 0xd9, 0xb2,
+	0x77, 0xff, 0xe5, 0x7c, 0xd3, 0x20, 0x72, 0xd9, 0xc2, 0x39, 0x24, 0xd9, 0x68, 0xc1, 0x49, 0x82,
+	0x35, 0x49, 0xa9, 0xd2, 0xe6, 0x5a, 0xa5, 0xb7, 0xa0, 0x7a, 0x14, 0xcd, 0x48, 0x66, 0x55, 0xa5,
+	0x5b, 0x19, 0xe8, 0x6b, 0x68, 0x8c, 0xa3, 0x73, 0x12, 0xd2, 0x98, 0x58, 0x35, 0x59, 0xfc, 0x8e,
+	0x23, 0xda, 0x9c, 0x3b, 0x47, 0xce, 0xb3, 0x65, 0x6f, 0xe7, 0xca, 0x9b, 0x15, 0x78, 0x5c, 0xd0,
+	0xa1, 0xbb, 0x50, 0x1b, 0x9f, 0x93, 0x88, 0x27, 0x56, 0x5d, 0xf6, 0xa7, 0xa5, 0xfa, 0x23, 0x7d,
+	0x58, 0x87, 0xd0, 0x5b, 0x50, 0xc3, 0x24, 0x49, 0x43, 0x6e, 0x35, 0xe4, 0xe9, 0x6d, 0x05, 0x52,
+	0x3e, 0xac, 0x63, 0xe8, 0x1e, 0xd4, 0x31, 0xf1, 0x48, 0x10, 0x73, 0xab, 0xa9, 0x61, 0xe2, 0x50,
+	0xed, 0xc3, 0x79, 0x10, 0x0d, 0xa0, 0x39, 0xce, 0x3c, 0x12, 0x8b, 0x1e, 0x59, 0x90, 0x6b, 0x49,
+	0x09, 0xba, 0x08, 0xe0, 0x15, 0xc6, 0xfe, 0x6d, 0x43, 0x54, 0x4b, 0xca, 0x61, 0xd5, 0x52, 0xe3,
+	0x06, 0x5b, 0xba, 0x71, 0x13, 0x2d, 0x7d, 0x07, 0x9a, 0xb2, 0x5c, 0x32, 0xbb, 0x8a, 0xcc, 0xae,
+	0xf3, 0x62, 0xd9, 0x5b, 0x39, 0xf1, 0x6a, 0x89, 0x2c, 0xa8, 0x4b, 0xe3, 0x68, 0x5f, 0x0a, 0xa0,
+	0x89, 0x73, 0xb3, 0xa4, 0x8c, 0xea, 0x7f, 0x2b, 0xa3, 0x56, 0x56, 0xc6, 0x5a, 0x2d, 0xeb, 0x57,
+	0xd7, 0xf2, 0x23, 0xf3, 0xe9, 0x2f, 0xbd, 0x5b, 0xf6, 0x8f, 0x1b, 0x50, 0x95, 0x07, 0x8a, 0xd6,
+	0xea, 0xa9, 0x36, 0xca, 0xad, 0xd5, 0x03, 0x9d, 0x97, 0xfd, 0x9e, 0x38, 0x3c, 0x4e, 0xb9, 0x1e,
+	0xfd, 0x4d, 0x05, 0x92, 0x2e, 0xa5, 0x14, 0x15, 0x46, 0x6f, 0x43, 0xed, 0x34, 0xe5, 0x02, 0x58,
+	0x29, 0xbf, 0x11, 0xca, 0xa7, 0x35, 0xa5, 0x0c, 0x74, 0x17, 0xcc, 0x4f, 0xdd, 0x30, 0x94, 0xd7,
+	0x6f, 0x0d, 0x5f, 0x53, 0x40, 0xe1, 0x51, 0x30, 0x19, 0x44, 0x7d, 0xa8, 0x1c, 0x53, 0x5f, 0x56,
+	0xa2, 0x35, 0xbc, 0xad, 0x30, 0xc7, 0xd4, 0x57, 0x10, 0x11, 0x42, 0x9f, 0x40, 0xe7, 0x80, 0x9e,
+	0x13, 0x16, 0xed, 0x79, 0x1e, 0x4d, 0x23, 0xae, 0xe7, 0xc3, 0x52, 0xd8, 0xb5, 0x90, 0xda, 0xb5,
+	0x0e, 0xd7, 0xf5, 0x78, 0x6a, 0xe4, 0x0a, 0x17, 0xf5, 0xc7, 0x84, 0xa7, 0x2c, 0x92, 0x05, 0x69,
+	0x63, 0x6d, 0x89, 0x8e, 0x1d, 0xb8, 0xc9, 0xe3, 0x84, 0xcc, 0x64, 0x11, 0x4c, 0x9c, 0x9b, 0x68,
+	0x07, 0x9a, 0x27, 0xee, 0x9c, 0x8c, 0x23, 0xce, 0x16, 0xfa, 0xde, 0x6d, 0x47, 0x3d, 0xc9, 0xd2,
+	0x87, 0x57, 0x61, 0xf4, 0x1e, 0x34, 0x3e, 0x27, 0x6c, 0xbe, 0xc7, 0xfc, 0x44, 0xdf, 0x7c, 0xcb,
+	0x29, 0xbd, 0xd2, 0x79, 0x0c, 0x17, 0x28, 0xfb, 0x2f, 0x03, 0x1a, 0xf9, 0x95, 0xd1, 0x09, 0xd4,
+	0xf7, 0x66, 0x33, 0x46, 0x92, 0x44, 0x65, 0x37, 0x7a, 0x5f, 0x6b, 0xf6, 0xdd, 0x97, 0x6b, 0xd6,
+	0x63, 0x8b, 0x98, 0x53, 0x47, 0xef, 0xc5, 0x39, 0x09, 0x3a, 0x02, 0x73, 0xdf, 0xe5, 0xee, 0xf5,
+	0x06, 0x40, 0x52, 0xa0, 0x63, 0xa8, 0x4d, 0x68, 0x1c, 0x78, 0xea, 0xa1, 0xff, 0xdf, 0x99, 0x69,
+	0xb2, 0xaf, 0x28, 0x9b, 0x0d, 0x77, 0x3f, 0xc0, 0x9a, 0xc3, 0xfe, 0xdb, 0x80, 0x66, 0x21, 0x06,
+	0xb4, 0x03, 0x0d, 0x61, 0xc8, 0x54, 0x8d, 0xb2, 0x16, 0x72, 0x2f, 0x2e, 0xe2, 0x22, 0x8f, 0x53,
+	0x16, 0xf8, 0x41, 0xa4, 0x2f, 0xf5, 0x6a, 0x15, 0xd2, 0x1c, 0xa8, 0x0b, 0xf0, 0x88, 0xbb, 0xde,
+	0x93, 0x7d, 0x12, 0x73, 0xf5, 0xf4, 0x9b, 0xb8, 0xe4, 0x11, 0x6f, 0x88, 0x56, 0x8b, 0x79, 0xad,
+	0x37, 0x44, 0x91, 0xd8, 0x5f, 0x00, 0xfa, 0xb7, 0x64, 0xd1, 0xc7, 0xd0, 0xd1, 0xf6, 0xe3, 0x78,
+	0xe6, 0x72, 0xa2, 0x6b, 0xf0, 0x86, 0x23, 0xbf, 0xe6, 0x13, 0x32, 0x8f, 0x43, 0x97, 0x13, 0x0d,
+	0xc1, 0xeb, 0x58, 0xfb, 0x5b, 0x80, 0xd5, 0x9c, 0xde, 0xb4, 0x80, 0xec, 0xef, 0xa0, 0x55, 0x1a,
+	0xee, 0x1b, 0xa7, 0xff, 0x79, 0x03, 0xd6, 0x3a, 0x2b, 0xd6, 0xfa, 0xa9, 0x7a, 0xe5, 0xce, 0x2a,
+	0x8e, 0x82, 0x8d, 0x5c, 0x4f, 0x27, 0x8a, 0xa3, 0x18, 0xa4, 0xca, 0xf5, 0x07, 0x69, 0x0b, 0xaa,
+	0x5f, 0xba, 0x61, 0x4a, 0xf4, 0x9f, 0x81, 0x32, 0xd0, 0x26, 0x54, 0x0e, 0xdc, 0x44, 0x7f, 0x13,
+	0xc4, 0x72, 0x34, 0xba, 0xb8, 0xec, 0x1a, 0xbf, 0x5f, 0x76, 0x8d, 0x3f, 0x2f, 0xbb, 0xc6, 0xaf,
+	0xcf, 0xbb, 0xc6, 0xc5, 0xf3, 0xae, 0xf1, 0xcd, 0x15, 0xe9, 0x93, 0xfc, 0xe7, 0x48, 0xae, 0xa6,
+	0x35, 0xf9, 0x2b, 0xf8, 0xe0, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa8, 0xaa, 0x48, 0xa0, 0x91,
+	0x0a, 0x00, 0x00,
 }
diff --git a/execution/execution.go b/execution/execution.go
index 32ee4cf8..2fe05f13 100644
--- a/execution/execution.go
+++ b/execution/execution.go
@@ -15,17 +15,16 @@
 package execution
 
 import (
+	"context"
 	"fmt"
 	"runtime/debug"
 	"sync"
 	"time"
 
-	"context"
-
 	"github.com/hyperledger/burrow/acm"
 	"github.com/hyperledger/burrow/acm/state"
+	"github.com/hyperledger/burrow/bcm"
 	"github.com/hyperledger/burrow/binary"
-	bcm "github.com/hyperledger/burrow/blockchain"
 	"github.com/hyperledger/burrow/crypto"
 	"github.com/hyperledger/burrow/event"
 	"github.com/hyperledger/burrow/execution/contexts"
@@ -36,7 +35,6 @@ import (
 	"github.com/hyperledger/burrow/logging/structure"
 	"github.com/hyperledger/burrow/txs"
 	"github.com/hyperledger/burrow/txs/payload"
-	"github.com/pkg/errors"
 	abciTypes "github.com/tendermint/tendermint/abci/types"
 )
 
@@ -83,7 +81,7 @@ type executor struct {
 	blockExecution *exec.BlockExecution
 	logger         *logging.Logger
 	vmOptions      []func(*evm.VM)
-	txExecutors    map[payload.Type]Context
+	contexts       map[payload.Type]Context
 }
 
 var _ BatchExecutor = (*executor)(nil)
@@ -92,20 +90,35 @@ var _ BatchExecutor = (*executor)(nil)
 func NewBatchChecker(backend ExecutorState, blockchain *bcm.Blockchain, logger *logging.Logger,
 	options ...ExecutionOption) BatchExecutor {
 
-	return newExecutor("CheckCache", false, backend, blockchain, event.NewNoOpPublisher(),
+	exe := newExecutor("CheckCache", false, backend, blockchain, event.NewNoOpPublisher(),
 		logger.WithScope("NewBatchExecutor"), options...)
+
+	return exe.AddContext(payload.TypeGovernance,
+		&contexts.GovernanceContext{
+			ValidatorSet: exe.blockchain.ValidatorChecker(),
+			StateWriter:  exe.stateCache,
+			Logger:       exe.logger,
+		},
+	)
 }
 
 func NewBatchCommitter(backend ExecutorState, blockchain *bcm.Blockchain, emitter event.Publisher, logger *logging.Logger,
 	options ...ExecutionOption) BatchCommitter {
 
-	return newExecutor("CommitCache", true, backend, blockchain, emitter,
+	exe := newExecutor("CommitCache", true, backend, blockchain, emitter,
 		logger.WithScope("NewBatchCommitter"), options...)
+
+	return exe.AddContext(payload.TypeGovernance,
+		&contexts.GovernanceContext{
+			ValidatorSet: exe.blockchain.ValidatorWriter(),
+			StateWriter:  exe.stateCache,
+			Logger:       exe.logger,
+		},
+	)
 }
 
 func newExecutor(name string, runCall bool, backend ExecutorState, blockchain *bcm.Blockchain, publisher event.Publisher,
 	logger *logging.Logger, options ...ExecutionOption) *executor {
-
 	exe := &executor{
 		runCall:      runCall,
 		state:        backend,
@@ -121,7 +134,7 @@ func newExecutor(name string, runCall bool, backend ExecutorState, blockchain *b
 	for _, option := range options {
 		option(exe)
 	}
-	exe.txExecutors = map[payload.Type]Context{
+	exe.contexts = map[payload.Type]Context{
 		payload.TypeSend: &contexts.SendContext{
 			Tip:         blockchain,
 			StateWriter: exe.stateCache,
@@ -145,15 +158,15 @@ func newExecutor(name string, runCall bool, backend ExecutorState, blockchain *b
 			StateWriter: exe.stateCache,
 			Logger:      exe.logger,
 		},
-		payload.TypeGovernance: &contexts.GovernanceContext{
-			ValidatorSet: blockchain,
-			StateWriter:  exe.stateCache,
-			Logger:       exe.logger,
-		},
 	}
 	return exe
 }
 
+func (exe *executor) AddContext(ty payload.Type, ctx Context) *executor {
+	exe.contexts[ty] = ctx
+	return exe
+}
+
 // If the tx is invalid, an error will be returned.
 // Unlike ExecBlock(), state will not be altered.
 func (exe *executor) Execute(txEnv *txs.Envelope) (txe *exec.TxExecution, err error) {
@@ -176,7 +189,7 @@ func (exe *executor) Execute(txEnv *txs.Envelope) (txe *exec.TxExecution, err er
 		return nil, err
 	}
 
-	if txExecutor, ok := exe.txExecutors[txEnv.Tx.Type()]; ok {
+	if txExecutor, ok := exe.contexts[txEnv.Tx.Type()]; ok {
 		// Establish new TxExecution
 		txe := exe.blockExecution.Tx(txEnv)
 		err = txExecutor.Execute(txe)
@@ -251,15 +264,17 @@ func (exe *executor) Commit(blockHash []byte, blockTime time.Time, header *abciT
 	}
 	publishErr := exe.publisher.Publish(context.Background(), blockExecution, blockExecution.Tagged())
 	exe.logger.InfoMsg("Error publishing TxExecution",
-		"height", blockExecution.Height,
-		structure.ErrorKey, publishErr)
-
+		"height", blockExecution.Height, structure.ErrorKey, publishErr)
 	// Commit to our blockchain state which will checkpoint the previous app hash by saving it to the database
 	// (we know the previous app hash is safely committed because we are about to commit the next)
-	err = exe.blockchain.CommitBlock(blockTime, blockHash, hash)
+	totalPowerChange, totalFlow, err := exe.blockchain.CommitBlock(blockTime, blockHash, hash)
 	if err != nil {
-		panic(errors.Wrap(err, "could not commit block to blockchain state"))
+		panic(fmt.Errorf("could not commit block to blockchain state: %v", err))
 	}
+	exe.logger.InfoMsg("Committed block",
+		"total_validator_power", exe.blockchain.CurrentValidators().TotalPower(),
+		"total_validator_power_change", totalPowerChange,
+		"total_validator_flow", totalFlow)
 
 	return hash, nil
 }
diff --git a/execution/execution_test.go b/execution/execution_test.go
index bfc4d96a..58b28ab4 100644
--- a/execution/execution_test.go
+++ b/execution/execution_test.go
@@ -17,16 +17,15 @@ package execution
 import (
 	"bytes"
 	"fmt"
+	"runtime/debug"
 	"strconv"
 	"testing"
 	"time"
 
-	"runtime/debug"
-
 	"github.com/hyperledger/burrow/acm"
 	"github.com/hyperledger/burrow/acm/state"
+	"github.com/hyperledger/burrow/bcm"
 	. "github.com/hyperledger/burrow/binary"
-	bcm "github.com/hyperledger/burrow/blockchain"
 	"github.com/hyperledger/burrow/crypto"
 	"github.com/hyperledger/burrow/event"
 	"github.com/hyperledger/burrow/execution/errors"
@@ -898,10 +897,10 @@ func TestSNativeTx(t *testing.T) {
 }
 
 func TestTxSequence(t *testing.T) {
-	state, privAccounts := makeGenesisState(3, true, 1000, 1, true, 1000)
-	acc0 := getAccount(state, privAccounts[0].Address())
+	st, privAccounts := makeGenesisState(3, true, 1000, 1, true, 1000)
+	acc0 := getAccount(st, privAccounts[0].Address())
 	acc0PubKey := privAccounts[0].PublicKey()
-	acc1 := getAccount(state, privAccounts[1].Address())
+	acc1 := getAccount(st, privAccounts[1].Address())
 
 	// Test a variety of sequence numbers for the tx.
 	// The tx should only pass when i == 1.
@@ -912,7 +911,7 @@ func TestTxSequence(t *testing.T) {
 		tx.AddOutput(acc1.Address(), 1)
 		txEnv := txs.Enclose(testChainID, tx)
 		require.NoError(t, txEnv.Sign(privAccounts[0]))
-		stateCopy, err := state.Copy(dbm.NewMemDB())
+		stateCopy, err := st.Copy(dbm.NewMemDB())
 		require.NoError(t, err)
 		err = execTxWithState(stateCopy, txEnv)
 		if i == 1 {
@@ -1033,7 +1032,7 @@ func TestNameTxs(t *testing.T) {
 
 	// fail to update it as non-owner
 	// Fast forward
-	for exe.blockchain.Tip.LastBlockHeight() < entry.Expires-1 {
+	for exe.blockchain.LastBlockHeight() < entry.Expires-1 {
 		commitNewBlock(st, exe.blockchain)
 	}
 	tx, _ = payload.NewNameTx(st, testPrivAccounts[1].PublicKey(), name, data, amt, fee)
@@ -1086,7 +1085,7 @@ func TestNameTxs(t *testing.T) {
 	require.NoError(t, err)
 	validateEntry(t, entry, name, data, testPrivAccounts[0].Address(), startingBlock+numDesiredBlocks)
 	// Fast forward
-	for exe.blockchain.Tip.LastBlockHeight() < entry.Expires {
+	for exe.blockchain.LastBlockHeight() < entry.Expires {
 		commitNewBlock(st, exe.blockchain)
 	}
 
@@ -1613,7 +1612,7 @@ func execTxWithStateNewBlock(state *State, blockchain *bcm.Blockchain, txEnv *tx
 }
 
 func makeGenesisState(numAccounts int, randBalance bool, minBalance uint64, numValidators int, randBonded bool,
-	minBonded int64) (*State, []acm.AddressableSigner) {
+	minBonded int64) (*State, []*acm.PrivateAccount) {
 	testGenesisDoc, privAccounts, _ := deterministicGenesis.GenesisDoc(numAccounts, randBalance, minBalance,
 		numValidators, randBonded, minBonded)
 	s0, err := MakeGenesisState(dbm.NewMemDB(), testGenesisDoc)
@@ -1625,7 +1624,10 @@ func makeGenesisState(numAccounts int, randBalance bool, minBalance uint64, numV
 }
 
 func getAccount(accountGetter state.AccountGetter, address crypto.Address) *acm.MutableAccount {
-	acc, _ := state.GetMutableAccount(accountGetter, address)
+	acc, err := state.GetMutableAccount(accountGetter, address)
+	if err != nil {
+		panic(err)
+	}
 	return acc
 }
 
@@ -1658,7 +1660,7 @@ func execTxWaitAccountCall(t *testing.T, exe *testExecutor, txEnv *txs.Envelope,
 	}
 	_, err = exe.Commit([]byte("Blocky McHash"), time.Now(), nil)
 	require.NoError(t, err)
-	err = exe.blockchain.CommitBlock(time.Time{}, nil, nil)
+	_, _, err = exe.blockchain.CommitBlock(time.Time{}, nil, nil)
 	require.NoError(t, err)
 
 	for _, ev := range evs.TaggedEvents().Filter(qry) {
@@ -1725,7 +1727,7 @@ func testSNativeTx(t *testing.T, expectPass bool, batchCommitter *testExecutor,
 		acc.MutablePermissions().Base.Set(perm, true)
 		batchCommitter.stateCache.UpdateAccount(acc)
 	}
-	tx, _ := payload.NewPermissionsTx(batchCommitter.stateCache, users[0].PublicKey(), snativeArgs)
+	tx, _ := payload.NewPermsTx(batchCommitter.stateCache, users[0].PublicKey(), snativeArgs)
 	txEnv := txs.Enclose(testChainID, tx)
 	require.NoError(t, txEnv.Sign(users[0]))
 	_, err := batchCommitter.Execute(txEnv)
diff --git a/execution/simulated_call.go b/execution/simulated_call.go
index d921b5e4..0274a739 100644
--- a/execution/simulated_call.go
+++ b/execution/simulated_call.go
@@ -6,8 +6,8 @@ import (
 
 	"github.com/hyperledger/burrow/acm"
 	"github.com/hyperledger/burrow/acm/state"
+	"github.com/hyperledger/burrow/bcm"
 	"github.com/hyperledger/burrow/binary"
-	"github.com/hyperledger/burrow/blockchain"
 	"github.com/hyperledger/burrow/crypto"
 	"github.com/hyperledger/burrow/execution/contexts"
 	"github.com/hyperledger/burrow/execution/evm"
@@ -17,7 +17,7 @@ import (
 
 // Run a contract's code on an isolated and unpersisted state
 // Cannot be used to create new contracts
-func CallSim(reader state.Reader, tip blockchain.TipInfo, fromAddress, address crypto.Address, data []byte,
+func CallSim(reader state.Reader, tip bcm.BlockchainInfo, fromAddress, address crypto.Address, data []byte,
 	logger *logging.Logger) (*exec.TxExecution, error) {
 
 	if evm.IsRegisteredNativeContract(address.Word256()) {
@@ -38,7 +38,7 @@ func CallSim(reader state.Reader, tip blockchain.TipInfo, fromAddress, address c
 
 // Run the given code on an isolated and unpersisted state
 // Cannot be used to create new contracts.
-func CallCodeSim(reader state.Reader, tip blockchain.TipInfo, fromAddress, address crypto.Address, code, data []byte,
+func CallCodeSim(reader state.Reader, tip bcm.BlockchainInfo, fromAddress, address crypto.Address, code, data []byte,
 	logger *logging.Logger) (_ *exec.TxExecution, err error) {
 	// This was being run against CheckTx cache, need to understand the reasoning
 	caller := acm.ConcreteAccount{Address: fromAddress}.MutableAccount()
@@ -65,7 +65,7 @@ func CallCodeSim(reader state.Reader, tip blockchain.TipInfo, fromAddress, addre
 	return txe, nil
 }
 
-func vmParams(tip blockchain.TipInfo) evm.Params {
+func vmParams(tip bcm.BlockchainInfo) evm.Params {
 	return evm.Params{
 		BlockHeight: tip.LastBlockHeight(),
 		BlockHash:   binary.LeftPadWord256(tip.LastBlockHash()),
diff --git a/execution/transactor.go b/execution/transactor.go
index 932e3129..c1a12edc 100644
--- a/execution/transactor.go
+++ b/execution/transactor.go
@@ -20,10 +20,11 @@ import (
 	"time"
 
 	"github.com/hyperledger/burrow/acm"
-	"github.com/hyperledger/burrow/blockchain"
+	"github.com/hyperledger/burrow/bcm"
 	"github.com/hyperledger/burrow/consensus/tendermint/codes"
 	"github.com/hyperledger/burrow/crypto"
 	"github.com/hyperledger/burrow/event"
+	"github.com/hyperledger/burrow/execution/errors"
 	"github.com/hyperledger/burrow/execution/exec"
 	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/logging/structure"
@@ -46,7 +47,7 @@ const (
 // for a key it holds or is provided - it is down to the key-holder to manage the mutual information between transactions
 // concurrent within a new block window.
 type Transactor struct {
-	Tip             blockchain.TipInfo
+	Tip             bcm.BlockchainInfo
 	Subscribable    event.Subscribable
 	MempoolAccounts *Accounts
 	checkTxAsync    func(tx tmTypes.Tx, cb func(*abciTypes.Response)) error
@@ -54,7 +55,7 @@ type Transactor struct {
 	logger          *logging.Logger
 }
 
-func NewTransactor(tip blockchain.TipInfo, subscribable event.Subscribable, mempoolAccounts *Accounts,
+func NewTransactor(tip bcm.BlockchainInfo, subscribable event.Subscribable, mempoolAccounts *Accounts,
 	checkTxAsync func(tx tmTypes.Tx, cb func(*abciTypes.Response)) error, txEncoder txs.Encoder,
 	logger *logging.Logger) *Transactor {
 
@@ -76,7 +77,7 @@ func (trans *Transactor) BroadcastTxSync(ctx context.Context, txEnv *txs.Envelop
 		var unlock UnlockFunc
 		txEnv, unlock, err = trans.SignTxMempool(txEnv)
 		if err != nil {
-			return nil, fmt.Errorf("error signing trnasction: %v", err)
+			return nil, fmt.Errorf("error signing transaction: %v", err)
 		}
 		defer unlock()
 	}
@@ -215,8 +216,8 @@ func (trans *Transactor) CheckTxSyncRaw(txBytes []byte) (*txs.Receipt, error) {
 			}
 			return receipt, nil
 		default:
-			return nil, fmt.Errorf("error returned by Tendermint in BroadcastTxSync "+
-				"ABCI code: %v, ABCI log: %v", checkTxResponse.Code, checkTxResponse.Log)
+			return nil, errors.ErrorCodef(errors.Code(checkTxResponse.Code),
+				"error returned by Tendermint in BroadcastTxSync ABCI log: %v", checkTxResponse.Log)
 		}
 	}
 }
diff --git a/execution/transactor_test.go b/execution/transactor_test.go
index 5d19f06f..3e9f82e6 100644
--- a/execution/transactor_test.go
+++ b/execution/transactor_test.go
@@ -17,11 +17,10 @@ package execution
 import (
 	"context"
 	"testing"
-	"time"
 
 	"github.com/hyperledger/burrow/acm"
 	"github.com/hyperledger/burrow/acm/state"
-	"github.com/hyperledger/burrow/blockchain"
+	"github.com/hyperledger/burrow/bcm"
 	"github.com/hyperledger/burrow/consensus/tendermint/codes"
 	"github.com/hyperledger/burrow/crypto"
 	"github.com/hyperledger/burrow/event"
@@ -38,7 +37,7 @@ import (
 
 func TestTransactor_BroadcastTxSync(t *testing.T) {
 	chainID := "TestChain"
-	tip := blockchain.NewTip(chainID, time.Time{}, []byte("genesis"), blockchain.NewValidators())
+	bc := &bcm.Blockchain{}
 	logger := logging.NewNoopLogger()
 	evc := event.NewEmitter(logger)
 	txCodec := txs.NewAminoCodec()
@@ -53,7 +52,7 @@ func TestTransactor_BroadcastTxSync(t *testing.T) {
 	err := txEnv.Sign(privAccount)
 	require.NoError(t, err)
 	height := uint64(35)
-	trans := NewTransactor(tip, evc, NewAccounts(state.NewMemoryState(), mock.NewKeyClient(privAccount), 100),
+	trans := NewTransactor(bc, evc, NewAccounts(state.NewMemoryState(), mock.NewKeyClient(privAccount), 100),
 		func(tx tmTypes.Tx, cb func(*abciTypes.Response)) error {
 			txe := exec.NewTxExecution(txEnv)
 			txe.Height = height
diff --git a/genesis/deterministic_genesis.go b/genesis/deterministic_genesis.go
index 15708c9e..d7da9d22 100644
--- a/genesis/deterministic_genesis.go
+++ b/genesis/deterministic_genesis.go
@@ -22,10 +22,10 @@ func NewDeterministicGenesis(seed int64) *deterministicGenesis {
 }
 
 func (dg *deterministicGenesis) GenesisDoc(numAccounts int, randBalance bool, minBalance uint64, numValidators int,
-	randBonded bool, minBonded int64) (*GenesisDoc, []acm.AddressableSigner, []acm.AddressableSigner) {
+	randBonded bool, minBonded int64) (*GenesisDoc, []*acm.PrivateAccount, []*acm.PrivateAccount) {
 
 	accounts := make([]Account, numAccounts)
-	privAccounts := make([]acm.AddressableSigner, numAccounts)
+	privAccounts := make([]*acm.PrivateAccount, numAccounts)
 	defaultPerms := permission.DefaultAccountPermissions
 	for i := 0; i < numAccounts; i++ {
 		account, privAccount := dg.Account(randBalance, minBalance)
@@ -39,7 +39,7 @@ func (dg *deterministicGenesis) GenesisDoc(numAccounts int, randBalance bool, mi
 		privAccounts[i] = privAccount
 	}
 	validators := make([]Validator, numValidators)
-	privValidators := make([]acm.AddressableSigner, numValidators)
+	privValidators := make([]*acm.PrivateAccount, numValidators)
 	for i := 0; i < numValidators; i++ {
 		validator := acm.GeneratePrivateAccountFromSecret(fmt.Sprintf("val_%v", i))
 		privValidators[i] = validator
@@ -66,7 +66,7 @@ func (dg *deterministicGenesis) GenesisDoc(numAccounts int, randBalance bool, mi
 
 }
 
-func (dg *deterministicGenesis) Account(randBalance bool, minBalance uint64) (acm.Account, acm.AddressableSigner) {
+func (dg *deterministicGenesis) Account(randBalance bool, minBalance uint64) (acm.Account, *acm.PrivateAccount) {
 	privateKey, err := crypto.GeneratePrivateKey(dg.random, crypto.CurveTypeEd25519)
 	if err != nil {
 		panic(fmt.Errorf("could not generate private key deterministically"))
diff --git a/genesis/genesis.go b/genesis/genesis.go
index c98607e1..bfc30c2f 100644
--- a/genesis/genesis.go
+++ b/genesis/genesis.go
@@ -22,6 +22,7 @@ import (
 	"time"
 
 	"github.com/hyperledger/burrow/acm"
+	"github.com/hyperledger/burrow/acm/validator"
 	"github.com/hyperledger/burrow/crypto"
 	"github.com/hyperledger/burrow/permission"
 )
@@ -66,6 +67,14 @@ type GenesisDoc struct {
 	Validators        []Validator
 }
 
+func (genesisDoc *GenesisDoc) JSONString() string {
+	bs, err := genesisDoc.JSONBytes()
+	if err != nil {
+		return fmt.Sprintf("error marshalling GenesisDoc: %v", err)
+	}
+	return string(bs)
+}
+
 // JSONBytes returns the JSON canonical bytes for a given GenesisDoc or an error.
 func (genesisDoc *GenesisDoc) JSONBytes() ([]byte, error) {
 	// Just in case
@@ -133,12 +142,13 @@ func (genesisAccount *Account) Clone() Account {
 //------------------------------------------------------------
 // Validator methods
 
-func (gv *Validator) Validator() acm.Validator {
-	return acm.ConcreteValidator{
-		Address:   gv.PublicKey.Address(),
+func (gv *Validator) Validator() validator.Validator {
+	address := gv.PublicKey.Address()
+	return validator.Validator{
+		Address:   &address,
 		PublicKey: gv.PublicKey,
 		Power:     uint64(gv.Amount),
-	}.Validator()
+	}
 }
 
 // Clone clones the genesis validator
@@ -175,7 +185,7 @@ func (basicAccount *BasicAccount) Clone() BasicAccount {
 // failure.  In particular MakeGenesisDocFromAccount uses the local time as a
 // timestamp for the GenesisDoc.
 func MakeGenesisDocFromAccounts(chainName string, salt []byte, genesisTime time.Time, accounts map[string]acm.Account,
-	validators map[string]acm.Validator) *GenesisDoc {
+	validators map[string]validator.Validator) *GenesisDoc {
 
 	// Establish deterministic order of accounts by name so we obtain identical GenesisDoc
 	// from identical input
@@ -202,15 +212,15 @@ func MakeGenesisDocFromAccounts(chainName string, salt []byte, genesisTime time.
 		genesisValidators = append(genesisValidators, Validator{
 			Name: name,
 			BasicAccount: BasicAccount{
-				Address:   val.Address(),
-				PublicKey: val.PublicKey(),
-				Amount:    val.Power(),
+				Address:   *val.Address,
+				PublicKey: val.PublicKey,
+				Amount:    val.Power,
 			},
 			// Simpler to just do this by convention
 			UnbondTo: []BasicAccount{
 				{
-					Amount:  val.Power(),
-					Address: val.Address(),
+					Amount:  val.Power,
+					Address: *val.Address,
 				},
 			},
 		})
diff --git a/genesis/genesis_test.go b/genesis/genesis_test.go
index 640bf18d..cfeb6f41 100644
--- a/genesis/genesis_test.go
+++ b/genesis/genesis_test.go
@@ -6,6 +6,7 @@ import (
 	"time"
 
 	"github.com/hyperledger/burrow/acm"
+	"github.com/hyperledger/burrow/acm/validator"
 	"github.com/hyperledger/burrow/permission"
 	"github.com/stretchr/testify/assert"
 )
@@ -41,10 +42,11 @@ func accountMap(names ...string) map[string]acm.Account {
 	return accounts
 }
 
-func validatorMap(names ...string) map[string]acm.Validator {
-	validators := make(map[string]acm.Validator, len(names))
+func validatorMap(names ...string) map[string]validator.Validator {
+	validators := make(map[string]validator.Validator, len(names))
 	for _, name := range names {
-		validators[name] = acm.AsValidator(accountFromName(name))
+		acc := accountFromName(name)
+		validators[name] = validator.FromAccount(acc, acc.Balance())
 	}
 	return validators
 }
diff --git a/genesis/spec/genesis_spec.go b/genesis/spec/genesis_spec.go
index de96d9a7..6990afa1 100644
--- a/genesis/spec/genesis_spec.go
+++ b/genesis/spec/genesis_spec.go
@@ -7,6 +7,7 @@ import (
 	"fmt"
 	"time"
 
+	"github.com/hyperledger/burrow/acm/balance"
 	"github.com/hyperledger/burrow/genesis"
 	"github.com/hyperledger/burrow/keys"
 	"github.com/hyperledger/burrow/permission"
@@ -68,9 +69,8 @@ func (gs *GenesisSpec) GenesisDoc(keyClient keys.KeyClient, generateNodeKeys boo
 
 	templateAccounts := gs.Accounts
 	if len(gs.Accounts) == 0 {
-		Power := DefaultPower
 		templateAccounts = append(templateAccounts, TemplateAccount{
-			Power: &Power,
+			Amounts: balance.New().Power(DefaultPower),
 		})
 	}
 
@@ -80,8 +80,8 @@ func (gs *GenesisSpec) GenesisDoc(keyClient keys.KeyClient, generateNodeKeys boo
 			return nil, fmt.Errorf("could not create Account from template: %v", err)
 		}
 		genesisDoc.Accounts = append(genesisDoc.Accounts, *account)
-		// Create a corresponding validator
-		if templateAccount.Power != nil {
+
+		if templateAccount.Balances().HasPower() {
 			// Note this does not modify the input template
 			templateAccount.Address = &account.Address
 			validator, err := templateAccount.Validator(keyClient, i, generateNodeKeys)
diff --git a/genesis/spec/genesis_spec_test.go b/genesis/spec/genesis_spec_test.go
index 98665055..1d52df39 100644
--- a/genesis/spec/genesis_spec_test.go
+++ b/genesis/spec/genesis_spec_test.go
@@ -3,6 +3,7 @@ package spec
 import (
 	"testing"
 
+	"github.com/hyperledger/burrow/acm/balance"
 	"github.com/hyperledger/burrow/crypto"
 	"github.com/hyperledger/burrow/keys/mock"
 	"github.com/hyperledger/burrow/permission"
@@ -17,7 +18,7 @@ func TestGenesisSpec_GenesisDoc(t *testing.T) {
 	amtBonded := uint64(100)
 	genesisSpec := GenesisSpec{
 		Accounts: []TemplateAccount{{
-			Power: &amtBonded,
+			Amounts: balance.New().Power(amtBonded),
 		}},
 	}
 
@@ -46,7 +47,7 @@ func TestGenesisSpec_GenesisDoc(t *testing.T) {
 				Address: &address,
 			},
 			{
-				Amount:      &amt,
+				Amounts:     balance.New().Native(amt),
 				Permissions: []string{permission.CreateAccountString, permission.CallString},
 			}},
 	}
diff --git a/genesis/spec/presets.go b/genesis/spec/presets.go
index 3025d98c..223ae0f4 100644
--- a/genesis/spec/presets.go
+++ b/genesis/spec/presets.go
@@ -3,6 +3,7 @@ package spec
 import (
 	"sort"
 
+	"github.com/hyperledger/burrow/acm/balance"
 	"github.com/hyperledger/burrow/permission"
 )
 
@@ -16,8 +17,7 @@ func FullAccount(name string) GenesisSpec {
 	return GenesisSpec{
 		Accounts: []TemplateAccount{{
 			Name:        name,
-			Amount:      &amount,
-			Power:       &Power,
+			Amounts:     balance.New().Native(amount).Power(Power),
 			Permissions: []string{permission.AllString},
 		},
 		},
@@ -30,7 +30,7 @@ func RootAccount(name string) GenesisSpec {
 	return GenesisSpec{
 		Accounts: []TemplateAccount{{
 			Name:        name,
-			Amount:      &amount,
+			Amounts:     balance.New().Native(amount),
 			Permissions: []string{permission.AllString},
 		},
 		},
@@ -42,8 +42,8 @@ func ParticipantAccount(name string) GenesisSpec {
 	amount := uint64(9999999999)
 	return GenesisSpec{
 		Accounts: []TemplateAccount{{
-			Name:   name,
-			Amount: &amount,
+			Name:    name,
+			Amounts: balance.New().Native(amount),
 			Permissions: []string{permission.SendString, permission.CallString, permission.NameString,
 				permission.HasRoleString},
 		}},
@@ -55,8 +55,8 @@ func DeveloperAccount(name string) GenesisSpec {
 	amount := uint64(9999999999)
 	return GenesisSpec{
 		Accounts: []TemplateAccount{{
-			Name:   name,
-			Amount: &amount,
+			Name:    name,
+			Amounts: balance.New().Native(amount),
 			Permissions: []string{permission.SendString, permission.CallString, permission.CreateContractString,
 				permission.CreateAccountString, permission.NameString, permission.HasRoleString,
 				permission.RemoveRoleString},
@@ -71,8 +71,7 @@ func ValidatorAccount(name string) GenesisSpec {
 	return GenesisSpec{
 		Accounts: []TemplateAccount{{
 			Name:        name,
-			Amount:      &amount,
-			Power:       &Power,
+			Amounts:     balance.New().Native(amount).Power(Power),
 			Permissions: []string{permission.BondString},
 		}},
 	}
@@ -146,8 +145,7 @@ func mergeAccount(base, override TemplateAccount) TemplateAccount {
 		base.Name = override.Name
 	}
 
-	base.Amount = addUint64Pointers(base.Amount, override.Amount)
-	base.Power = addUint64Pointers(base.Power, override.Power)
+	base.Amounts = base.Balances().Sum(override.Balances())
 
 	base.Permissions = mergeStrings(base.Permissions, override.Permissions)
 	base.Roles = mergeStrings(base.Roles, override.Roles)
diff --git a/genesis/spec/presets_test.go b/genesis/spec/presets_test.go
index 762e397b..1c11015f 100644
--- a/genesis/spec/presets_test.go
+++ b/genesis/spec/presets_test.go
@@ -3,6 +3,7 @@ package spec
 import (
 	"testing"
 
+	"github.com/hyperledger/burrow/acm/balance"
 	"github.com/hyperledger/burrow/keys/mock"
 	"github.com/hyperledger/burrow/permission"
 	"github.com/stretchr/testify/assert"
@@ -43,7 +44,7 @@ func TestMergeGenesisSpecsRepeatedAccounts(t *testing.T) {
 		Accounts: []TemplateAccount{
 			{
 				Name:        name1,
-				Amount:      &amt1,
+				Amounts:     balance.New().Native(amt1),
 				Permissions: []string{permission.SendString, permission.CreateAccountString, permission.HasRoleString},
 				Roles:       []string{"fooer"},
 			},
@@ -53,7 +54,7 @@ func TestMergeGenesisSpecsRepeatedAccounts(t *testing.T) {
 		Accounts: []TemplateAccount{
 			{
 				Name:        name1,
-				Amount:      &amt2,
+				Amounts:     balance.New().Native(amt2),
 				Permissions: []string{permission.SendString, permission.CreateAccountString},
 				Roles:       []string{"barer"},
 			},
@@ -62,8 +63,8 @@ func TestMergeGenesisSpecsRepeatedAccounts(t *testing.T) {
 	gs3 := GenesisSpec{
 		Accounts: []TemplateAccount{
 			{
-				Name:   name3,
-				Amount: &amt3,
+				Name:    name3,
+				Amounts: balance.New().Native(amt3),
 			},
 		},
 	}
@@ -77,7 +78,7 @@ func TestMergeGenesisSpecsRepeatedAccounts(t *testing.T) {
 		Accounts: []TemplateAccount{
 			{
 				Name:        name1,
-				Amount:      &amtExpected,
+				Amounts:     balance.New().Native(amtExpected),
 				Permissions: []string{permission.CreateAccountString, permission.HasRoleString, permission.SendString},
 				Roles:       []string{"barer", "fooer"},
 			},
diff --git a/genesis/spec/spec.pb.go b/genesis/spec/spec.pb.go
index 9d568bfd..ffaaef3a 100644
--- a/genesis/spec/spec.pb.go
+++ b/genesis/spec/spec.pb.go
@@ -18,6 +18,7 @@ import fmt "fmt"
 import math "math"
 import _ "github.com/gogo/protobuf/gogoproto"
 import crypto "github.com/hyperledger/burrow/crypto"
+import balance "github.com/hyperledger/burrow/acm/balance"
 
 import github_com_hyperledger_burrow_crypto "github.com/hyperledger/burrow/crypto"
 
@@ -36,14 +37,13 @@ var _ = math.Inf
 const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
 
 type TemplateAccount struct {
-	Name        string                                        `protobuf:"bytes,1,opt,name=Name" json:"Name"`
-	Address     *github_com_hyperledger_burrow_crypto.Address `protobuf:"bytes,2,opt,name=Address,customtype=github.com/hyperledger/burrow/crypto.Address" json:",omitempty" toml:",omitempty"`
-	NodeAddress *github_com_hyperledger_burrow_crypto.Address `protobuf:"bytes,3,opt,name=NodeAddress,customtype=github.com/hyperledger/burrow/crypto.Address" json:",omitempty" toml:",omitempty"`
+	Name        string                                        `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"`
+	Address     *github_com_hyperledger_burrow_crypto.Address `protobuf:"bytes,2,opt,name=Address,proto3,customtype=github.com/hyperledger/burrow/crypto.Address" json:",omitempty" toml:",omitempty"`
+	NodeAddress *github_com_hyperledger_burrow_crypto.Address `protobuf:"bytes,3,opt,name=NodeAddress,proto3,customtype=github.com/hyperledger/burrow/crypto.Address" json:",omitempty" toml:",omitempty"`
 	PublicKey   *crypto.PublicKey                             `protobuf:"bytes,4,opt,name=PublicKey" json:",omitempty" toml:",omitempty"`
-	Amount      *uint64                                       `protobuf:"varint,5,opt,name=Amount" json:",omitempty" toml:",omitempty"`
-	Power       *uint64                                       `protobuf:"varint,6,opt,name=Power" json:",omitempty" toml:",omitempty"`
-	Permissions []string                                      `protobuf:"bytes,7,rep,name=Permissions" json:",omitempty" toml:",omitempty"`
-	Roles       []string                                      `protobuf:"bytes,8,rep,name=Roles" json:",omitempty" toml:",omitempty"`
+	Amounts     []balance.Balance                             `protobuf:"bytes,5,rep,name=Amounts" json:",omitempty" toml:",omitempty"`
+	Permissions []string                                      `protobuf:"bytes,6,rep,name=Permissions" json:",omitempty" toml:",omitempty"`
+	Roles       []string                                      `protobuf:"bytes,7,rep,name=Roles" json:",omitempty" toml:",omitempty"`
 }
 
 func (m *TemplateAccount) Reset()                    { *m = TemplateAccount{} }
@@ -65,18 +65,11 @@ func (m *TemplateAccount) GetPublicKey() *crypto.PublicKey {
 	return nil
 }
 
-func (m *TemplateAccount) GetAmount() uint64 {
-	if m != nil && m.Amount != nil {
-		return *m.Amount
-	}
-	return 0
-}
-
-func (m *TemplateAccount) GetPower() uint64 {
-	if m != nil && m.Power != nil {
-		return *m.Power
+func (m *TemplateAccount) GetAmounts() []balance.Balance {
+	if m != nil {
+		return m.Amounts
 	}
-	return 0
+	return nil
 }
 
 func (m *TemplateAccount) GetPermissions() []string {
@@ -115,10 +108,12 @@ func (m *TemplateAccount) MarshalTo(dAtA []byte) (int, error) {
 	_ = i
 	var l int
 	_ = l
-	dAtA[i] = 0xa
-	i++
-	i = encodeVarintSpec(dAtA, i, uint64(len(m.Name)))
-	i += copy(dAtA[i:], m.Name)
+	if len(m.Name) > 0 {
+		dAtA[i] = 0xa
+		i++
+		i = encodeVarintSpec(dAtA, i, uint64(len(m.Name)))
+		i += copy(dAtA[i:], m.Name)
+	}
 	if m.Address != nil {
 		dAtA[i] = 0x12
 		i++
@@ -149,19 +144,21 @@ func (m *TemplateAccount) MarshalTo(dAtA []byte) (int, error) {
 		}
 		i += n3
 	}
-	if m.Amount != nil {
-		dAtA[i] = 0x28
-		i++
-		i = encodeVarintSpec(dAtA, i, uint64(*m.Amount))
-	}
-	if m.Power != nil {
-		dAtA[i] = 0x30
-		i++
-		i = encodeVarintSpec(dAtA, i, uint64(*m.Power))
+	if len(m.Amounts) > 0 {
+		for _, msg := range m.Amounts {
+			dAtA[i] = 0x2a
+			i++
+			i = encodeVarintSpec(dAtA, i, uint64(msg.Size()))
+			n, err := msg.MarshalTo(dAtA[i:])
+			if err != nil {
+				return 0, err
+			}
+			i += n
+		}
 	}
 	if len(m.Permissions) > 0 {
 		for _, s := range m.Permissions {
-			dAtA[i] = 0x3a
+			dAtA[i] = 0x32
 			i++
 			l = len(s)
 			for l >= 1<<7 {
@@ -176,7 +173,7 @@ func (m *TemplateAccount) MarshalTo(dAtA []byte) (int, error) {
 	}
 	if len(m.Roles) > 0 {
 		for _, s := range m.Roles {
-			dAtA[i] = 0x42
+			dAtA[i] = 0x3a
 			i++
 			l = len(s)
 			for l >= 1<<7 {
@@ -205,7 +202,9 @@ func (m *TemplateAccount) Size() (n int) {
 	var l int
 	_ = l
 	l = len(m.Name)
-	n += 1 + l + sovSpec(uint64(l))
+	if l > 0 {
+		n += 1 + l + sovSpec(uint64(l))
+	}
 	if m.Address != nil {
 		l = m.Address.Size()
 		n += 1 + l + sovSpec(uint64(l))
@@ -218,11 +217,11 @@ func (m *TemplateAccount) Size() (n int) {
 		l = m.PublicKey.Size()
 		n += 1 + l + sovSpec(uint64(l))
 	}
-	if m.Amount != nil {
-		n += 1 + sovSpec(uint64(*m.Amount))
-	}
-	if m.Power != nil {
-		n += 1 + sovSpec(uint64(*m.Power))
+	if len(m.Amounts) > 0 {
+		for _, e := range m.Amounts {
+			l = e.Size()
+			n += 1 + l + sovSpec(uint64(l))
+		}
 	}
 	if len(m.Permissions) > 0 {
 		for _, s := range m.Permissions {
@@ -408,10 +407,10 @@ func (m *TemplateAccount) Unmarshal(dAtA []byte) error {
 			}
 			iNdEx = postIndex
 		case 5:
-			if wireType != 0 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType)
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Amounts", wireType)
 			}
-			var v uint64
+			var msglen int
 			for shift := uint(0); ; shift += 7 {
 				if shift >= 64 {
 					return ErrIntOverflowSpec
@@ -421,33 +420,24 @@ func (m *TemplateAccount) Unmarshal(dAtA []byte) error {
 				}
 				b := dAtA[iNdEx]
 				iNdEx++
-				v |= (uint64(b) & 0x7F) << shift
+				msglen |= (int(b) & 0x7F) << shift
 				if b < 0x80 {
 					break
 				}
 			}
-			m.Amount = &v
-		case 6:
-			if wireType != 0 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Power", wireType)
+			if msglen < 0 {
+				return ErrInvalidLengthSpec
 			}
-			var v uint64
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowSpec
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				v |= (uint64(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
 			}
-			m.Power = &v
-		case 7:
+			m.Amounts = append(m.Amounts, balance.Balance{})
+			if err := m.Amounts[len(m.Amounts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 6:
 			if wireType != 2 {
 				return fmt.Errorf("proto: wrong wireType = %d for field Permissions", wireType)
 			}
@@ -476,7 +466,7 @@ func (m *TemplateAccount) Unmarshal(dAtA []byte) error {
 			}
 			m.Permissions = append(m.Permissions, string(dAtA[iNdEx:postIndex]))
 			iNdEx = postIndex
-		case 8:
+		case 7:
 			if wireType != 2 {
 				return fmt.Errorf("proto: wrong wireType = %d for field Roles", wireType)
 			}
@@ -635,28 +625,28 @@ func init() { proto.RegisterFile("spec.proto", fileDescriptorSpec) }
 func init() { golang_proto.RegisterFile("spec.proto", fileDescriptorSpec) }
 
 var fileDescriptorSpec = []byte{
-	// 359 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x92, 0x3f, 0x6f, 0xe2, 0x30,
-	0x18, 0x87, 0xf1, 0x11, 0xe0, 0x30, 0x48, 0x27, 0x3c, 0x59, 0x0c, 0x49, 0xc4, 0x2d, 0xd1, 0x89,
-	0x23, 0xd2, 0x6d, 0x47, 0x97, 0x12, 0xa9, 0x53, 0x25, 0x84, 0x28, 0x53, 0x37, 0x92, 0xbc, 0x0d,
-	0x91, 0x62, 0x1c, 0xd9, 0x8e, 0x50, 0x3e, 0x4e, 0xbf, 0x49, 0x47, 0x46, 0xe6, 0x0e, 0x51, 0x05,
-	0x43, 0xa5, 0x8e, 0xfd, 0x04, 0x55, 0x42, 0x28, 0x4c, 0x55, 0x96, 0x6e, 0xef, 0x1f, 0x3d, 0xbf,
-	0xc7, 0xb2, 0x8d, 0xb1, 0x8c, 0xc1, 0x1b, 0xc5, 0x82, 0x2b, 0x4e, 0xb4, 0xbc, 0xee, 0xff, 0x0d,
-	0x42, 0xb5, 0x4a, 0xdc, 0x91, 0xc7, 0x99, 0x1d, 0xf0, 0x80, 0xdb, 0xc5, 0xd2, 0x4d, 0x1e, 0x8a,
-	0xae, 0x68, 0x8a, 0xea, 0x08, 0xf5, 0xbb, 0x9e, 0x48, 0x63, 0x55, 0x76, 0x83, 0x57, 0x0d, 0xff,
-	0x5a, 0x00, 0x8b, 0xa3, 0xa5, 0x82, 0x89, 0xe7, 0xf1, 0x64, 0xad, 0x08, 0xc5, 0xda, 0x74, 0xc9,
-	0x80, 0x22, 0x13, 0x59, 0x6d, 0x47, 0xdb, 0x66, 0x46, 0x6d, 0x5e, 0x4c, 0x08, 0xc3, 0xad, 0x89,
-	0xef, 0x0b, 0x90, 0x92, 0xfe, 0x30, 0x91, 0xd5, 0x75, 0xee, 0x9e, 0x33, 0x63, 0x78, 0xe1, 0x5f,
-	0xa5, 0x31, 0x88, 0x08, 0xfc, 0x00, 0x84, 0xed, 0x26, 0x42, 0xf0, 0x8d, 0x5d, 0xea, 0x4a, 0xee,
-	0x2d, 0x33, 0xf0, 0x90, 0xb3, 0x50, 0x01, 0x8b, 0x55, 0xfa, 0x9e, 0x19, 0x3d, 0xc5, 0x59, 0x34,
-	0x1e, 0x9c, 0x67, 0x83, 0xf9, 0xc9, 0x41, 0x12, 0xdc, 0x99, 0x72, 0x1f, 0x4e, 0xca, 0xfa, 0xf7,
-	0x29, 0x2f, 0x3d, 0x64, 0x81, 0xdb, 0xb3, 0xc4, 0x8d, 0x42, 0xef, 0x16, 0x52, 0xaa, 0x99, 0xc8,
-	0xea, 0xfc, 0xeb, 0x8d, 0xca, 0xcc, 0xcf, 0x85, 0xf3, 0xbb, 0x4a, 0xee, 0x39, 0x88, 0x5c, 0xe1,
-	0xe6, 0x84, 0xe5, 0xf7, 0x4b, 0x1b, 0x26, 0xb2, 0xb4, 0x6a, 0x7c, 0x89, 0x90, 0xff, 0xb8, 0x31,
-	0xe3, 0x1b, 0x10, 0xb4, 0x59, 0x9d, 0x3d, 0x12, 0xe4, 0x06, 0x77, 0x66, 0x20, 0x58, 0x28, 0x65,
-	0xc8, 0xd7, 0x92, 0xb6, 0xcc, 0xba, 0xd5, 0xae, 0x16, 0x70, 0xc9, 0xe5, 0x27, 0x98, 0xf3, 0x08,
-	0x24, 0xfd, 0x59, 0x3d, 0xe0, 0x48, 0x8c, 0xb5, 0xdd, 0xa3, 0x51, 0x73, 0xae, 0xb7, 0x7b, 0x1d,
-	0xed, 0xf6, 0x3a, 0x7a, 0xd9, 0xeb, 0xe8, 0xe9, 0xa0, 0xa3, 0xed, 0x41, 0x47, 0xf7, 0x7f, 0xbe,
-	0x7e, 0xc9, 0x00, 0xd6, 0x20, 0x43, 0x69, 0xe7, 0x1f, 0xfd, 0x23, 0x00, 0x00, 0xff, 0xff, 0x4b,
-	0xcc, 0xe3, 0x66, 0xfb, 0x02, 0x00, 0x00,
+	// 367 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x52, 0xbf, 0x6f, 0xda, 0x40,
+	0x14, 0xee, 0x15, 0x03, 0xe2, 0x4c, 0xd5, 0x72, 0x93, 0xc5, 0x60, 0x5b, 0x74, 0xa8, 0x55, 0x51,
+	0x5b, 0xa2, 0x53, 0x3b, 0x15, 0x4b, 0x9d, 0x22, 0x21, 0x04, 0x4c, 0xd9, 0xfc, 0xe3, 0xc5, 0x58,
+	0xf2, 0xf9, 0xac, 0xbb, 0xb3, 0x22, 0xff, 0x67, 0x19, 0x33, 0x32, 0x66, 0xce, 0x60, 0x45, 0xb0,
+	0x65, 0xcc, 0x5f, 0x10, 0x61, 0xe3, 0xc0, 0x14, 0x79, 0xc9, 0x74, 0xdf, 0x77, 0x4f, 0xdf, 0xf7,
+	0x3d, 0xbd, 0xf7, 0x30, 0x16, 0x19, 0x04, 0x76, 0xc6, 0x99, 0x64, 0x44, 0x39, 0xe2, 0xf1, 0xaf,
+	0x28, 0x96, 0xdb, 0xdc, 0xb7, 0x03, 0x46, 0x9d, 0x88, 0x45, 0xcc, 0xa9, 0x8a, 0x7e, 0x7e, 0x53,
+	0xb1, 0x8a, 0x54, 0xa8, 0x16, 0x8d, 0x87, 0x01, 0x2f, 0x32, 0xd9, 0xb0, 0x2f, 0xbe, 0x97, 0x78,
+	0x69, 0x00, 0x35, 0x9d, 0xdc, 0x29, 0xf8, 0xeb, 0x06, 0x68, 0x96, 0x78, 0x12, 0xe6, 0x41, 0xc0,
+	0xf2, 0x54, 0x12, 0x82, 0x95, 0x85, 0x47, 0x41, 0x43, 0x26, 0xb2, 0x06, 0xab, 0x0a, 0x13, 0x8a,
+	0xfb, 0xf3, 0x30, 0xe4, 0x20, 0x84, 0xf6, 0xd9, 0x44, 0xd6, 0xd0, 0x5d, 0x3f, 0x96, 0xc6, 0xf4,
+	0xa2, 0x91, 0x6d, 0x91, 0x01, 0x4f, 0x20, 0x8c, 0x80, 0x3b, 0x7e, 0xce, 0x39, 0xbb, 0x75, 0x4e,
+	0xb9, 0x27, 0xdd, 0x73, 0x69, 0xe0, 0x29, 0xa3, 0xb1, 0x04, 0x9a, 0xc9, 0xe2, 0xa5, 0x34, 0x46,
+	0x92, 0xd1, 0xe4, 0xef, 0xe4, 0xfc, 0x37, 0x59, 0x35, 0x19, 0x24, 0xc7, 0xea, 0x82, 0x85, 0xd0,
+	0x44, 0x76, 0x3e, 0x2e, 0xf2, 0x32, 0x87, 0x6c, 0xf0, 0x60, 0x99, 0xfb, 0x49, 0x1c, 0x5c, 0x41,
+	0xa1, 0x29, 0x26, 0xb2, 0xd4, 0xd9, 0xc8, 0x3e, 0x79, 0xbe, 0x15, 0xdc, 0xef, 0x6d, 0x7c, 0xcf,
+	0x46, 0x64, 0x8d, 0xfb, 0x73, 0x7a, 0x9c, 0xac, 0xd0, 0xba, 0x66, 0xc7, 0x52, 0x67, 0xdf, 0xec,
+	0x66, 0x09, 0x6e, 0xfd, 0xba, 0x3f, 0x76, 0xa5, 0xf1, 0xa9, 0xdd, 0x84, 0x6a, 0x27, 0xf2, 0x1f,
+	0xab, 0x4b, 0xe0, 0x34, 0x16, 0x22, 0x66, 0xa9, 0xd0, 0x7a, 0x66, 0xc7, 0x1a, 0xb4, 0xeb, 0xec,
+	0x52, 0x47, 0xfe, 0xe0, 0xee, 0x8a, 0x25, 0x20, 0xb4, 0x7e, 0x7b, 0x83, 0x5a, 0xe1, 0xfe, 0xdb,
+	0xed, 0x75, 0xf4, 0xb0, 0xd7, 0xd1, 0xd3, 0x5e, 0x47, 0xf7, 0x07, 0x1d, 0xed, 0x0e, 0x3a, 0xba,
+	0xfe, 0xf9, 0xfe, 0x82, 0x22, 0x48, 0x41, 0xc4, 0xc2, 0x39, 0x1e, 0xb2, 0xdf, 0xab, 0x6e, 0xf0,
+	0xf7, 0x6b, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8b, 0xc3, 0x66, 0xb6, 0xe3, 0x02, 0x00, 0x00,
 }
diff --git a/genesis/spec/template_account.go b/genesis/spec/template_account.go
index b4ce1fa4..152a8097 100644
--- a/genesis/spec/template_account.go
+++ b/genesis/spec/template_account.go
@@ -3,6 +3,7 @@ package spec
 import (
 	"fmt"
 
+	"github.com/hyperledger/burrow/acm/balance"
 	"github.com/hyperledger/burrow/crypto"
 	"github.com/hyperledger/burrow/genesis"
 	"github.com/hyperledger/burrow/keys"
@@ -24,11 +25,7 @@ func (ta TemplateAccount) Validator(keyClient keys.KeyClient, index int, generat
 		}
 		ta.NodeAddress = &address
 	}
-	if ta.Power == nil {
-		gv.Amount = DefaultPower
-	} else {
-		gv.Amount = *ta.Power
-	}
+	gv.Amount = ta.Balances().GetPower(DefaultPower)
 	if ta.Name == "" {
 		gv.Name = accountNameFromIndex(index)
 	} else {
@@ -62,11 +59,7 @@ func (ta TemplateAccount) GenesisAccount(keyClient keys.KeyClient, index int) (*
 	if err != nil {
 		return nil, err
 	}
-	if ta.Amount == nil {
-		ga.Amount = DefaultAmount
-	} else {
-		ga.Amount = *ta.Amount
-	}
+	ga.Amount = ta.Balances().GetNative(DefaultAmount)
 	if ta.Name == "" {
 		ga.Name = accountNameFromIndex(index)
 	} else {
@@ -111,3 +104,7 @@ func (ta TemplateAccount) RealisePubKeyAndAddress(keyClient keys.KeyClient) (pub
 	}
 	return
 }
+
+func (ta TemplateAccount) Balances() balance.Balances {
+	return ta.Amounts
+}
diff --git a/governance/governance.go b/governance/governance.go
index b3e56f5b..5ea2e125 100644
--- a/governance/governance.go
+++ b/governance/governance.go
@@ -2,6 +2,14 @@
 // validators, and network forks.
 package governance
 
+import (
+	"github.com/hyperledger/burrow/acm/balance"
+	"github.com/hyperledger/burrow/crypto"
+	"github.com/hyperledger/burrow/genesis/spec"
+	"github.com/hyperledger/burrow/permission"
+	"github.com/hyperledger/burrow/txs/payload"
+)
+
 // TODO:
 // - Set validator power
 // - Set account amount(s)
@@ -15,3 +23,33 @@ package governance
 // - Network administered proxies (i.e. instead of keys have password authentication for identities - allow calls to originate as if from address without key?)
 // Subject to:
 // - Less than 1/3 validator power change per block
+
+// Creates a GovTx that alters the validator power of id to the power passed
+func AlterPowerTx(inputAddress crypto.Address, id crypto.Addressable, power uint64) *payload.GovTx {
+	return AlterBalanceTx(inputAddress, id, balance.New().Power(power))
+}
+
+func AlterBalanceTx(inputAddress crypto.Address, id crypto.Addressable, bal balance.Balances) *payload.GovTx {
+	publicKey := id.PublicKey()
+	return UpdateAccountTx(inputAddress, &spec.TemplateAccount{
+		PublicKey: &publicKey,
+		Amounts:   bal,
+	})
+}
+
+func AlterPermissionsTx(inputAddress crypto.Address, id crypto.Addressable, perms permission.PermFlag) *payload.GovTx {
+	address := id.Address()
+	return UpdateAccountTx(inputAddress, &spec.TemplateAccount{
+		Address:     &address,
+		Permissions: permission.PermFlagToStringList(perms),
+	})
+}
+
+func UpdateAccountTx(inputAddress crypto.Address, updates ...*spec.TemplateAccount) *payload.GovTx {
+	return &payload.GovTx{
+		Inputs: []*payload.TxInput{{
+			Address: inputAddress,
+		}},
+		AccountUpdates: updates,
+	}
+}
diff --git a/governance/governance_test.go b/governance/governance_test.go
new file mode 100644
index 00000000..42d4d396
--- /dev/null
+++ b/governance/governance_test.go
@@ -0,0 +1,23 @@
+package governance
+
+import (
+	"testing"
+
+	"github.com/hyperledger/burrow/acm"
+	"github.com/hyperledger/burrow/execution/exec"
+	"github.com/hyperledger/burrow/txs"
+	"github.com/stretchr/testify/require"
+)
+
+func TestSerialise(t *testing.T) {
+	priv := acm.GeneratePrivateAccountFromSecret("hhelo")
+	tx := AlterPowerTx(priv.Address(), priv, 3242323)
+	txEnv := txs.Enclose("OOh", tx)
+
+	txe := exec.NewTxExecution(txEnv)
+	bs, err := txe.Marshal()
+	require.NoError(t, err)
+	txeOut := new(exec.TxExecution)
+	err = txeOut.Unmarshal(bs)
+	require.NoError(t, err)
+}
diff --git a/integration/core/kernel_test.go b/integration/core/kernel_test.go
index 4459af6c..3850fbc9 100644
--- a/integration/core/kernel_test.go
+++ b/integration/core/kernel_test.go
@@ -5,75 +5,75 @@ package core
 import (
 	"context"
 	"fmt"
-	"os"
 	"testing"
 	"time"
 
 	"github.com/hyperledger/burrow/config"
-	"github.com/hyperledger/burrow/consensus/tendermint/validator"
+	"github.com/hyperledger/burrow/consensus/tendermint"
 	"github.com/hyperledger/burrow/core"
 	"github.com/hyperledger/burrow/event"
 	"github.com/hyperledger/burrow/execution/exec"
 	"github.com/hyperledger/burrow/genesis"
 	"github.com/hyperledger/burrow/integration"
+	"github.com/hyperledger/burrow/integration/rpctest"
 	"github.com/hyperledger/burrow/keys"
+	"github.com/hyperledger/burrow/keys/mock"
 	"github.com/hyperledger/burrow/logging"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
-	tmConfig "github.com/tendermint/tendermint/config"
 	tmTypes "github.com/tendermint/tendermint/types"
 )
 
-const testDir = "./test_scratch/kernel_test"
+var genesisDoc, privateAccounts, privateValidators = genesis.NewDeterministicGenesis(123).GenesisDoc(1, true, 1000, 1, true, 1000)
 
 func TestBootThenShutdown(t *testing.T) {
-	os.RemoveAll(testDir)
-	os.MkdirAll(testDir, 0777)
-	os.Chdir(testDir)
-	defer os.RemoveAll(testDir)
-	tmConf := tmConfig.DefaultConfig()
+	cleanup := integration.EnterTestDirectory()
+	defer cleanup()
 	//logger, _, _ := lifecycle.NewStdErrLogger()
 	logger := logging.NewNoopLogger()
-	genesisDoc, _, privateValidators := genesis.NewDeterministicGenesis(123).GenesisDoc(1, true, 1000, 1, true, 1000)
-	privValidator := validator.NewPrivValidatorMemory(privateValidators[0], privateValidators[0])
-	assert.NoError(t, bootWaitBlocksShutdown(privValidator, integration.NewTestConfig(genesisDoc), tmConf, logger, nil))
+	privValidator := tendermint.NewPrivValidatorMemory(privateValidators[0], privateValidators[0])
+	assert.NoError(t, bootWaitBlocksShutdown(t, privValidator, integration.NewTestConfig(genesisDoc), logger, nil))
 }
 
 func TestBootShutdownResume(t *testing.T) {
-	os.RemoveAll(testDir)
-	os.MkdirAll(testDir, 0777)
-	os.Chdir(testDir)
-	defer os.RemoveAll(testDir)
-	tmConf := tmConfig.DefaultConfig()
-	//logger, _, _ := lifecycle.NewStdErrLogger()
+	cleanup := integration.EnterTestDirectory()
+	defer cleanup()
+	//logger, _ := lifecycle.NewStdErrLogger()
 	logger := logging.NewNoopLogger()
-	genesisDoc, _, privateValidators := genesis.NewDeterministicGenesis(123).GenesisDoc(1, true, 1000, 1, true, 1000)
-	privValidator := validator.NewPrivValidatorMemory(privateValidators[0], privateValidators[0])
+	privValidator := tendermint.NewPrivValidatorMemory(privateValidators[0], privateValidators[0])
 
+	testConfig := integration.NewTestConfig(genesisDoc)
 	i := uint64(0)
 	// asserts we get a consecutive run of blocks
 	blockChecker := func(block *exec.BlockExecution) bool {
-		assert.Equal(t, i+1, block.Height)
+		if i == 0 {
+			// We send some synchronous transactions so catch up to latest block
+			i = block.Height - 1
+		}
+		require.Equal(t, i+1, block.Height)
 		i++
 		// stop every third block
-		return i%3 != 0
+		if i%3 == 0 {
+			i = 0
+			return false
+		}
+		return true
 	}
-	testConfig := integration.NewTestConfig(genesisDoc)
 	// First run
-	require.NoError(t, bootWaitBlocksShutdown(privValidator, testConfig, tmConf, logger, blockChecker))
+	require.NoError(t, bootWaitBlocksShutdown(t, privValidator, testConfig, logger, blockChecker))
 	// Resume and check we pick up where we left off
-	require.NoError(t, bootWaitBlocksShutdown(privValidator, testConfig, tmConf, logger, blockChecker))
+	require.NoError(t, bootWaitBlocksShutdown(t, privValidator, testConfig, logger, blockChecker))
 	// Resuming with mismatched genesis should fail
 	genesisDoc.Salt = []byte("foo")
-	assert.Error(t, bootWaitBlocksShutdown(privValidator, testConfig, tmConf, logger, blockChecker))
+	assert.Error(t, bootWaitBlocksShutdown(t, privValidator, testConfig, logger, blockChecker))
 }
 
-func bootWaitBlocksShutdown(privValidator tmTypes.PrivValidator, testConfig *config.BurrowConfig,
-	tmConf *tmConfig.Config, logger *logging.Logger,
+func bootWaitBlocksShutdown(t testing.TB, privValidator tmTypes.PrivValidator, testConfig *config.BurrowConfig,
+	logger *logging.Logger,
 	blockChecker func(block *exec.BlockExecution) (cont bool)) error {
 
 	keyStore := keys.NewKeyStore(keys.DefaultKeysDir, false, logger)
-	keyClient := keys.NewLocalKeyClient(keyStore, logging.NewNoopLogger())
+	keyClient := mock.NewKeyClient(privateAccounts...)
 	kern, err := core.NewKernel(context.Background(), keyClient, privValidator,
 		testConfig.GenesisDoc,
 		testConfig.Tendermint.TendermintConfig(),
@@ -89,6 +89,13 @@ func bootWaitBlocksShutdown(privValidator tmTypes.PrivValidator, testConfig *con
 		return err
 	}
 
+	inputAddress := privateAccounts[0].Address()
+	tcli := rpctest.NewTransactClient(t, testConfig.RPC.GRPC.ListenAddress)
+	// Generate a few transactions
+	for i := 0; i < 3; i++ {
+		rpctest.CreateContract(t, tcli, inputAddress)
+	}
+
 	subID := event.GenSubID()
 	ch, err := kern.Emitter.Subscribe(context.Background(), subID, exec.QueryForBlockExecution(), 10)
 	if err != nil {
diff --git a/integration/governance/governance_test.go b/integration/governance/governance_test.go
new file mode 100644
index 00000000..b188331c
--- /dev/null
+++ b/integration/governance/governance_test.go
@@ -0,0 +1,172 @@
+// +build integration
+
+package governance
+
+import (
+	"context"
+	"fmt"
+	"math/big"
+	"testing"
+
+	"github.com/hyperledger/burrow/acm"
+	"github.com/hyperledger/burrow/acm/balance"
+	"github.com/hyperledger/burrow/acm/validator"
+	"github.com/hyperledger/burrow/crypto"
+	"github.com/hyperledger/burrow/execution/errors"
+	"github.com/hyperledger/burrow/execution/exec"
+	"github.com/hyperledger/burrow/governance"
+	"github.com/hyperledger/burrow/integration/rpctest"
+	"github.com/hyperledger/burrow/permission"
+	"github.com/hyperledger/burrow/rpc/rpcevents"
+	"github.com/hyperledger/burrow/rpc/rpcquery"
+	"github.com/hyperledger/burrow/rpc/rpctransact"
+	"github.com/hyperledger/burrow/txs/payload"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+	"github.com/tendermint/tendermint/rpc/core"
+)
+
+func TestAlterValidators(t *testing.T) {
+	inputAddress := privateAccounts[0].Address()
+	grpcAddress := testConfigs[0].RPC.GRPC.ListenAddress
+	tcli := rpctest.NewTransactClient(t, grpcAddress)
+	qcli := rpctest.NewQueryClient(t, grpcAddress)
+	ecli := rpctest.NewExecutionEventsClient(t, grpcAddress)
+
+	// Build a batch of validator alterations to make
+	vs := validator.NewTrimSet()
+	alterPower(vs, 3, 2131)
+	alterPower(vs, 2, 4561)
+	alterPower(vs, 5, 7831)
+	alterPower(vs, 8, 9931)
+
+	vs.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) {
+		_, err := govSync(t, tcli, governance.AlterPowerTx(inputAddress, id, power.Uint64()))
+		require.NoError(t, err)
+		return
+	})
+
+	vsOut := getValidatorHistory(t, qcli)
+	// Include the genesis validator and compare the sets
+	alterPower(vs, 0, genesisDoc.Validators[0].Amount)
+	assertValidatorsEqual(t, vs, vsOut)
+
+	// Remove validator from chain
+	txe, err := govSync(t, tcli, governance.AlterPowerTx(inputAddress, account(3), 0))
+	// Mirror in our check set
+	alterPower(vs, 3, 0)
+	fmt.Println(txe.Events)
+	vsOut = getValidatorHistory(t, qcli)
+	assertValidatorsEqual(t, vs, vsOut)
+
+	waitNBlocks(t, ecli, 3)
+	height := int64(kernels[4].Blockchain.LastBlockHeight())
+	kernels[4].Node.ConfigureRPC()
+	tmVals, err := core.Validators(&height)
+	require.NoError(t, err)
+	vsOut = validator.NewTrimSet()
+
+	for _, v := range tmVals.Validators {
+		publicKey, err := crypto.PublicKeyFromTendermintPubKey(v.PubKey)
+		require.NoError(t, err)
+		vsOut.AlterPower(publicKey, big.NewInt(v.VotingPower))
+	}
+	assertValidatorsEqual(t, vs, vsOut)
+}
+
+func TestNoRootPermission(t *testing.T) {
+	grpcAddress := testConfigs[0].RPC.GRPC.ListenAddress
+	tcli := rpctest.NewTransactClient(t, grpcAddress)
+	// Account does not have Root permission
+	inputAddress := privateAccounts[4].Address()
+	_, err := govSync(t, tcli, governance.AlterPowerTx(inputAddress, account(5), 3433))
+	require.Error(t, err)
+	assert.Contains(t, err.Error(), errors.ErrorCodePermissionDenied.Error())
+}
+
+func TestAlterAmount(t *testing.T) {
+	inputAddress := privateAccounts[0].Address()
+	grpcAddress := testConfigs[0].RPC.GRPC.ListenAddress
+	tcli := rpctest.NewTransactClient(t, grpcAddress)
+	qcli := rpctest.NewQueryClient(t, grpcAddress)
+	var amount uint64 = 18889
+	acc := account(5)
+	_, err := govSync(t, tcli, governance.AlterBalanceTx(inputAddress, acc, balance.New().Native(amount)))
+	require.NoError(t, err)
+	ca, err := qcli.GetAccount(context.Background(), &rpcquery.GetAccountParam{Address: acc.Address()})
+	require.NoError(t, err)
+	assert.Equal(t, amount, ca.Balance)
+}
+
+func TestAlterPermissions(t *testing.T) {
+	inputAddress := privateAccounts[0].Address()
+	grpcAddress := testConfigs[0].RPC.GRPC.ListenAddress
+	tcli := rpctest.NewTransactClient(t, grpcAddress)
+	qcli := rpctest.NewQueryClient(t, grpcAddress)
+	acc := account(5)
+	_, err := govSync(t, tcli, governance.AlterPermissionsTx(inputAddress, acc, permission.Send))
+	require.NoError(t, err)
+	ca, err := qcli.GetAccount(context.Background(), &rpcquery.GetAccountParam{Address: acc.Address()})
+	require.NoError(t, err)
+	assert.Equal(t, permission.AccountPermissions{
+		Base: permission.BasePermissions{
+			Perms:  permission.Send,
+			SetBit: permission.Send,
+		},
+	}, ca.Permissions)
+}
+
+func TestCreateAccount(t *testing.T) {
+	inputAddress := privateAccounts[0].Address()
+	grpcAddress := testConfigs[0].RPC.GRPC.ListenAddress
+	tcli := rpctest.NewTransactClient(t, grpcAddress)
+	qcli := rpctest.NewQueryClient(t, grpcAddress)
+	var amount uint64 = 18889
+	acc := acm.GeneratePrivateAccountFromSecret("we almost certainly don't exist")
+	_, err := govSync(t, tcli, governance.AlterBalanceTx(inputAddress, acc, balance.New().Native(amount)))
+	require.NoError(t, err)
+	ca, err := qcli.GetAccount(context.Background(), &rpcquery.GetAccountParam{Address: acc.Address()})
+	require.NoError(t, err)
+	assert.Equal(t, amount, ca.Balance)
+}
+
+func getValidatorHistory(t testing.TB, qcli rpcquery.QueryClient) *validator.Set {
+	history, err := qcli.GetValidatorSet(context.Background(), &rpcquery.GetValidatorSetParam{
+		IncludeHistory: true,
+	})
+	require.NoError(t, err)
+
+	// Include the genesis validator and compare the sets
+	return validator.UnpersistSet(history.Set)
+}
+
+func account(i int) *acm.PrivateAccount {
+	return rpctest.PrivateAccounts[i]
+}
+
+func govSync(t testing.TB, cli rpctransact.TransactClient, tx *payload.GovTx) (*exec.TxExecution, error) {
+	return cli.BroadcastTxSync(context.Background(), &rpctransact.TxEnvelopeParam{
+		Payload: tx.Any(),
+	})
+}
+
+func assertValidatorsEqual(t testing.TB, expected, actual *validator.Set) {
+	if !assert.True(t, expected.Equal(actual), "sets should be equal") {
+		fmt.Printf("Expected:\n%v\nActual:\n%v\n", expected, actual)
+	}
+}
+
+func alterPower(vs *validator.Set, i int, power uint64) {
+	vs.AlterPower(account(i), new(big.Int).SetUint64(power))
+}
+
+func waitNBlocks(t testing.TB, ecli rpcevents.ExecutionEventsClient, n int) {
+	stream, err := ecli.GetBlocks(context.Background(), &rpcevents.BlocksRequest{
+		BlockRange: rpcevents.NewBlockRange(rpcevents.LatestBound(), rpcevents.StreamBound()),
+	})
+	defer stream.CloseSend()
+	for i := 0; i < n; i++ {
+		require.NoError(t, err)
+		_, err = stream.Recv()
+	}
+}
diff --git a/integration/governance/main_test.go b/integration/governance/main_test.go
index 21b39516..65e338e3 100644
--- a/integration/governance/main_test.go
+++ b/integration/governance/main_test.go
@@ -21,28 +21,59 @@ import (
 	"context"
 	"os"
 	"testing"
+	"time"
 
+	"github.com/hyperledger/burrow/config"
 	"github.com/hyperledger/burrow/core"
 	"github.com/hyperledger/burrow/integration"
-	"github.com/hyperledger/burrow/integration/rpctest"
+	"github.com/hyperledger/burrow/logging/logconfig"
+	"github.com/hyperledger/burrow/permission"
 )
 
+var privateAccounts = integration.MakePrivateAccounts(10) // make keys
+var genesisDoc = integration.TestGenesisDoc(privateAccounts)
 var _ = integration.ClaimPorts()
-var inputAddress = rpctest.PrivateAccounts[0].Address()
-var gene
-var testConfig = integration.NewTestConfig(rpctest.GenesisDoc)
-var kern *core.Kernel
+var testConfigs []*config.BurrowConfig
+var kernels []*core.Kernel
 
 // Needs to be in a _test.go file to be picked up
 func TestMain(m *testing.M) {
-	kern = integration.TestKernel(rpctest.PrivateAccounts, testConfig)
-	err := kern.Boot()
+	cleanup := integration.EnterTestDirectory()
+	defer cleanup()
+	testConfigs = make([]*config.BurrowConfig, len(privateAccounts))
+	kernels = make([]*core.Kernel, len(privateAccounts))
+	genesisDoc.Accounts[4].Permissions = permission.NewAccountPermissions(permission.Send | permission.Call)
+	for i, acc := range privateAccounts {
+		testConfig := integration.NewTestConfig(genesisDoc)
+		testConfigs[i] = testConfig
+		kernels[i] = integration.TestKernel(acc, privateAccounts, testConfigs[i],
+			logconfig.New().Root(func(sink *logconfig.SinkConfig) *logconfig.SinkConfig {
+				return sink.SetTransform(logconfig.FilterTransform(logconfig.IncludeWhenAllMatch,
+					"total_validator")).SetOutput(logconfig.StdoutOutput())
+			}))
+		err := kernels[i].Boot()
+		if err != nil {
+			panic(err)
+		}
+		// Sometimes better to not shutdown as logging errors on shutdown may obscure real issue
+		defer func() {
+			kernels[i].Shutdown(context.Background())
+		}()
+	}
+	time.Sleep(1 * time.Second)
+	for i := 0; i < len(kernels); i++ {
+		for j := i; j < len(kernels); j++ {
+			if i != j {
+				connectKernels(kernels[i], kernels[j])
+			}
+		}
+	}
+	os.Exit(m.Run())
+}
+
+func connectKernels(k1, k2 *core.Kernel) {
+	err := k1.Node.Switch().DialPeerWithAddress(k2.Node.NodeInfo().NetAddress(), false)
 	if err != nil {
 		panic(err)
 	}
-	// Sometimes better to not shutdown as logging errors on shutdown may obscure real issue
-	defer func() {
-		kern.Shutdown(context.Background())
-	}()
-	os.Exit(m.Run())
 }
diff --git a/integration/governance/validators_test.go b/integration/governance/validators_test.go
deleted file mode 100644
index 07b8008d..00000000
--- a/integration/governance/validators_test.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package governance
-
-import "testing"
-
-func TestName(t *testing.T) {
-
-}
diff --git a/integration/integration.go b/integration/integration.go
index 280f8320..ae3cf0ba 100644
--- a/integration/integration.go
+++ b/integration/integration.go
@@ -25,27 +25,25 @@ import (
 	"time"
 
 	"github.com/hyperledger/burrow/acm"
+	"github.com/hyperledger/burrow/acm/validator"
 	"github.com/hyperledger/burrow/config"
-	"github.com/hyperledger/burrow/consensus/tendermint/validator"
+	"github.com/hyperledger/burrow/consensus/tendermint"
 	"github.com/hyperledger/burrow/core"
 	"github.com/hyperledger/burrow/execution/evm/sha3"
 	"github.com/hyperledger/burrow/genesis"
 	"github.com/hyperledger/burrow/keys/mock"
 	"github.com/hyperledger/burrow/logging"
-	lConfig "github.com/hyperledger/burrow/logging/config"
 	"github.com/hyperledger/burrow/logging/lifecycle"
-	"github.com/hyperledger/burrow/logging/structure"
+	lConfig "github.com/hyperledger/burrow/logging/logconfig"
 	"github.com/hyperledger/burrow/permission"
 )
 
 const (
-	chainName = "Integration_Test_Chain"
+	ChainName = "Integration_Test_Chain"
 	testDir   = "./test_scratch/tm_test"
 )
 
 // Enable logger output during tests
-//var debugLogging = true
-var debugLogging = false
 
 // Starting point for assigning range of ports for tests
 // Start at unprivileged port (hoping for the best)
@@ -58,41 +56,25 @@ const startingPortBuckets = 1000
 // Mutable port to assign to next claimant
 var port = uint32(startingPort)
 
-// We use this to wrap tests
-func TestKernel(privateAccounts []*acm.PrivateAccount, testConfig *config.BurrowConfig) *core.Kernel {
-	fmt.Println("Running with integration TestWrapper (core/integration/integration.go)...")
-
-	os.RemoveAll(testDir)
-	os.MkdirAll(testDir, 0777)
-	os.Chdir(testDir)
-	defer os.RemoveAll(testDir)
+var node uint64 = 0
 
-	os.MkdirAll("config", 0777)
+// We use this to wrap tests
+func TestKernel(validatorAccount *acm.PrivateAccount, keysAccounts []*acm.PrivateAccount,
+	testConfig *config.BurrowConfig, loggingConfig *lConfig.LoggingConfig) *core.Kernel {
+	fmt.Println("Creating integration test Kernel...")
 
 	logger := logging.NewNoopLogger()
-	if debugLogging {
+	if loggingConfig != nil {
 		var err error
 		// Change config as needed
-		logger, err = lifecycle.NewLoggerFromLoggingConfig(&lConfig.LoggingConfig{
-			ExcludeTrace: false,
-			RootSink: lConfig.Sink().
-				SetTransform(lConfig.FilterTransform(lConfig.IncludeWhenAnyMatches,
-					structure.ComponentKey, "Tendermint",
-					structure.ScopeKey, "executor.Execute\\(tx txs.Tx\\)",
-				)).
-				//AddSinks(config.Sink().SetTransform(config.FilterTransform(config.ExcludeWhenAnyMatches, "run_call", "false")).
-				AddSinks(lConfig.Sink().SetTransform(lConfig.PruneTransform("log_channel", "trace", "scope", "returns", "run_id", "args")).
-					AddSinks(lConfig.Sink().SetTransform(lConfig.SortTransform("tx_hash", "time", "message", "method")).
-						SetOutput(lConfig.StdoutOutput()))),
-		})
+		logger, err = lifecycle.NewLoggerFromLoggingConfig(loggingConfig)
 		if err != nil {
 			panic(err)
 		}
 	}
 
-	validatorAccount := privateAccounts[0]
-	privValidator := validator.NewPrivValidatorMemory(validatorAccount, validatorAccount)
-	keyClient := mock.NewKeyClient(privateAccounts...)
+	privValidator := tendermint.NewPrivValidatorMemory(validatorAccount, validatorAccount)
+	keyClient := mock.NewKeyClient(keysAccounts...)
 	kernel, err := core.NewKernel(context.Background(), keyClient, privValidator,
 		testConfig.GenesisDoc,
 		testConfig.Tendermint.TendermintConfig(),
@@ -106,6 +88,14 @@ func TestKernel(privateAccounts []*acm.PrivateAccount, testConfig *config.Burrow
 	return kernel
 }
 
+func EnterTestDirectory() (cleanup func()) {
+	os.RemoveAll(testDir)
+	os.MkdirAll(testDir, 0777)
+	os.Chdir(testDir)
+	os.MkdirAll("config", 0777)
+	return func() { os.RemoveAll(testDir) }
+}
+
 func TestGenesisDoc(addressables []*acm.PrivateAccount) *genesis.GenesisDoc {
 	accounts := make(map[string]acm.Account, len(addressables))
 	for i, pa := range addressables {
@@ -118,9 +108,9 @@ func TestGenesisDoc(addressables []*acm.PrivateAccount) *genesis.GenesisDoc {
 	if err != nil {
 		panic("could not parse test genesis time")
 	}
-	return genesis.MakeGenesisDocFromAccounts(chainName, nil, genesisTime, accounts,
-		map[string]acm.Validator{
-			"genesis_validator": acm.AsValidator(accounts["user_0"]),
+	return genesis.MakeGenesisDocFromAccounts(ChainName, nil, genesisTime, accounts,
+		map[string]validator.Validator{
+			"genesis_validator": validator.FromAccount(accounts["user_0"], 1<<16),
 		})
 }
 
@@ -152,17 +142,26 @@ func GetPort() uint16 {
 	return uint16(atomic.AddUint32(&port, 1))
 }
 
+// Gets an name based on an incrementing counter for running multiple nodes
+func GetName() string {
+	nodeNumber := atomic.AddUint64(&node, 1)
+	return fmt.Sprintf("node_%03d", nodeNumber)
+}
+
 func GetLocalAddress() string {
-	return fmt.Sprintf("localhost:%v", GetPort())
+	return fmt.Sprintf("127.0.0.1:%v", GetPort())
 }
 
 func GetTCPLocalAddress() string {
-	return fmt.Sprintf("tcp://localhost:%v", GetPort())
+	return fmt.Sprintf("tcp://127.0.0.1:%v", GetPort())
 }
 
 func NewTestConfig(genesisDoc *genesis.GenesisDoc) *config.BurrowConfig {
+	name := GetName()
 	cnf := config.DefaultBurrowConfig()
 	cnf.GenesisDoc = genesisDoc
+	cnf.Tendermint.Moniker = name
+	cnf.Tendermint.TendermintRoot = fmt.Sprintf(".burrow_%s", name)
 	cnf.Tendermint.ListenAddress = GetTCPLocalAddress()
 	cnf.RPC.GRPC.ListenAddress = GetLocalAddress()
 	cnf.RPC.Metrics.ListenAddress = GetTCPLocalAddress()
diff --git a/integration/integration_test.go b/integration/integration_test.go
new file mode 100644
index 00000000..485a5bd9
--- /dev/null
+++ b/integration/integration_test.go
@@ -0,0 +1,28 @@
+// 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 integration
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestNamesAndPorts(t *testing.T) {
+	assert.Equal(t, "node_001", GetName())
+	assert.Equal(t, "node_002", GetName())
+	assert.Equal(t, startingPort+1, GetPort())
+	assert.Equal(t, startingPort+2, GetPort())
+}
diff --git a/integration/rpcevents/main_test.go b/integration/rpcevents/main_test.go
index 1a842bd9..1acbd46f 100644
--- a/integration/rpcevents/main_test.go
+++ b/integration/rpcevents/main_test.go
@@ -34,7 +34,9 @@ var kern *core.Kernel
 
 // Needs to be in a _test.go file to be picked up
 func TestMain(m *testing.M) {
-	kern = integration.TestKernel(rpctest.PrivateAccounts, testConfig)
+	cleanup := integration.EnterTestDirectory()
+	defer cleanup()
+	kern = integration.TestKernel(rpctest.PrivateAccounts[0], rpctest.PrivateAccounts, testConfig, nil)
 	err := kern.Boot()
 	if err != nil {
 		panic(err)
diff --git a/integration/rpcquery/main_test.go b/integration/rpcquery/main_test.go
index 9f13b06b..d6e9694e 100644
--- a/integration/rpcquery/main_test.go
+++ b/integration/rpcquery/main_test.go
@@ -33,7 +33,9 @@ var kern *core.Kernel
 
 // Needs to be in a _test.go file to be picked up
 func TestMain(m *testing.M) {
-	kern = integration.TestKernel(rpctest.PrivateAccounts, testConfig)
+	cleanup := integration.EnterTestDirectory()
+	defer cleanup()
+	kern = integration.TestKernel(rpctest.PrivateAccounts[0], rpctest.PrivateAccounts, testConfig, nil)
 	err := kern.Boot()
 	if err != nil {
 		panic(err)
diff --git a/integration/rpctransact/main_test.go b/integration/rpctransact/main_test.go
index 1f773a00..5b0d3d05 100644
--- a/integration/rpctransact/main_test.go
+++ b/integration/rpctransact/main_test.go
@@ -33,7 +33,9 @@ var kern *core.Kernel
 
 // Needs to be in a _test.go file to be picked up
 func TestMain(m *testing.M) {
-	kern = integration.TestKernel(rpctest.PrivateAccounts, testConfig)
+	cleanup := integration.EnterTestDirectory()
+	defer cleanup()
+	kern = integration.TestKernel(rpctest.PrivateAccounts[0], rpctest.PrivateAccounts, testConfig, nil)
 	err := kern.Boot()
 	if err != nil {
 		panic(err)
diff --git a/integration/rpctransact/transact_server_test.go b/integration/rpctransact/transact_server_test.go
index 096f80b2..1132faf6 100644
--- a/integration/rpctransact/transact_server_test.go
+++ b/integration/rpctransact/transact_server_test.go
@@ -88,7 +88,7 @@ func TestBroadcastTxLocallySigned(t *testing.T) {
 
 func TestFormulateTx(t *testing.T) {
 	cli := rpctest.NewTransactClient(t, testConfig.RPC.GRPC.ListenAddress)
-	txEnv, err := cli.FormulateTx(context.Background(), &rpctransact.PayloadParam{
+	txEnv, err := cli.FormulateTx(context.Background(), &payload.Any{
 		CallTx: &payload.CallTx{
 			Input: &payload.TxInput{
 				Address: inputAddress,
diff --git a/integration/tm/main_test.go b/integration/tm/main_test.go
index 627fa6d2..44e733ab 100644
--- a/integration/tm/main_test.go
+++ b/integration/tm/main_test.go
@@ -41,7 +41,9 @@ var clients = map[string]tmClient.RPCClient{
 
 // Needs to be in a _test.go file to be picked up
 func TestMain(m *testing.M) {
-	kern = integration.TestKernel(rpctest.PrivateAccounts, testConfig)
+	cleanup := integration.EnterTestDirectory()
+	defer cleanup()
+	kern = integration.TestKernel(rpctest.PrivateAccounts[0], rpctest.PrivateAccounts, testConfig, nil)
 	err := kern.Boot()
 	if err != nil {
 		panic(err)
diff --git a/logging/config/presets/instructions_test.go b/logging/config/presets/instructions_test.go
deleted file mode 100644
index c8398cc5..00000000
--- a/logging/config/presets/instructions_test.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package presets
-
-import (
-	"testing"
-
-	"github.com/hyperledger/burrow/logging/config"
-	"github.com/hyperledger/burrow/logging/loggers"
-	"github.com/hyperledger/burrow/logging/structure"
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
-)
-
-func TestBuildSinkConfig(t *testing.T) {
-	builtSink, err := BuildSinkConfig(IncludeAny, Info, Stdout, Terminal, Down, Down, Info, Stdout, Up, Info, Stderr)
-	require.NoError(t, err)
-	expectedSink := config.Sink().
-		SetTransform(config.FilterTransform(config.IncludeWhenAnyMatches,
-			structure.ChannelKey, structure.InfoChannelName)).SetOutput(config.StdoutOutput().SetFormat(loggers.TerminalFormat)).AddSinks(
-		config.Sink().SetTransform(config.FilterTransform(config.NoFilterMode,
-			structure.ChannelKey, structure.InfoChannelName)).SetOutput(config.StderrOutput()).AddSinks(
-			config.Sink().SetTransform(config.FilterTransform(config.NoFilterMode,
-				structure.ChannelKey, structure.InfoChannelName)).SetOutput(config.StdoutOutput())))
-
-	//fmt.Println(config.JSONString(expectedSink), "\n", config.JSONString(builtSink))
-	assert.Equal(t, config.JSONString(expectedSink), config.JSONString(builtSink))
-}
-
-func TestMinimalPreset(t *testing.T) {
-	builtSink, err := BuildSinkConfig(Minimal, Stderr)
-	require.NoError(t, err)
-	expectedSink := config.Sink().
-		AddSinks(config.Sink().SetTransform(config.PruneTransform(structure.TraceKey, structure.RunId)).
-			AddSinks(config.Sink().SetTransform(config.FilterTransform(config.IncludeWhenAllMatch,
-				structure.ChannelKey, structure.InfoChannelName)).
-				AddSinks(config.Sink().SetTransform(config.FilterTransform(config.ExcludeWhenAnyMatches,
-					structure.ComponentKey, "Tendermint",
-					"module", "p2p",
-					"module", "mempool")).SetOutput(config.StderrOutput()))))
-	//fmt.Println(config.TOMLString(expectedSink), "\n", config.TOMLString(builtSink))
-	assert.Equal(t, config.TOMLString(expectedSink), config.TOMLString(builtSink))
-}
-
-func TestFileOutput(t *testing.T) {
-	path := "foo.log"
-	builtSink, err := BuildSinkConfig(Down, File, path, JSON)
-	require.NoError(t, err)
-	expectedSink := config.Sink().
-		AddSinks(config.Sink().SetOutput(config.FileOutput(path).SetFormat(loggers.JSONFormat)))
-	//fmt.Println(config.TOMLString(expectedSink), "\n", config.TOMLString(builtSink))
-	assert.Equal(t, config.TOMLString(expectedSink), config.TOMLString(builtSink))
-}
diff --git a/logging/config/sort.go b/logging/config/sort.go
deleted file mode 100644
index d912156b..00000000
--- a/logging/config/sort.go
+++ /dev/null
@@ -1 +0,0 @@
-package config
diff --git a/logging/lifecycle/lifecycle.go b/logging/lifecycle/lifecycle.go
index f17622e6..911525bf 100644
--- a/logging/lifecycle/lifecycle.go
+++ b/logging/lifecycle/lifecycle.go
@@ -21,7 +21,7 @@ import (
 	"time"
 
 	"github.com/hyperledger/burrow/logging/adapters/stdlib"
-	"github.com/hyperledger/burrow/logging/config"
+	"github.com/hyperledger/burrow/logging/logconfig"
 	"github.com/hyperledger/burrow/logging/loggers"
 	"github.com/hyperledger/burrow/logging/structure"
 
@@ -37,7 +37,7 @@ import (
 // to set up their root logger and capture any other logging output.
 
 // Obtain a logger from a LoggingConfig
-func NewLoggerFromLoggingConfig(loggingConfig *config.LoggingConfig) (*logging.Logger, error) {
+func NewLoggerFromLoggingConfig(loggingConfig *logconfig.LoggingConfig) (*logging.Logger, error) {
 	if loggingConfig == nil {
 		return NewStdErrLogger()
 	} else {
@@ -61,7 +61,7 @@ func NewLoggerFromLoggingConfig(loggingConfig *config.LoggingConfig) (*logging.L
 
 // Hot swap logging config by replacing output loggers of passed InfoTraceLogger
 // with those built from loggingConfig
-func SwapOutputLoggersFromLoggingConfig(logger *logging.Logger, loggingConfig *config.LoggingConfig) (error, channels.Channel) {
+func SwapOutputLoggersFromLoggingConfig(logger *logging.Logger, loggingConfig *logconfig.LoggingConfig) (error, channels.Channel) {
 	outputLogger, errCh, err := loggerFromLoggingConfig(loggingConfig)
 	if err != nil {
 		return err, channels.NewDeadChannel()
@@ -99,7 +99,7 @@ func CaptureStdlibLogOutput(infoTraceLogger *logging.Logger) {
 }
 
 // Helpers
-func loggerFromLoggingConfig(loggingConfig *config.LoggingConfig) (kitlog.Logger, channels.Channel, error) {
+func loggerFromLoggingConfig(loggingConfig *logconfig.LoggingConfig) (kitlog.Logger, channels.Channel, error) {
 	outputLogger, _, err := loggingConfig.RootSink.BuildLogger()
 	if err != nil {
 		return nil, nil, err
diff --git a/logging/config/config.go b/logging/logconfig/config.go
similarity index 84%
rename from logging/config/config.go
rename to logging/logconfig/config.go
index 8616aeb7..d5ffd0e8 100644
--- a/logging/config/config.go
+++ b/logging/logconfig/config.go
@@ -1,4 +1,4 @@
-package config
+package logconfig
 
 import (
 	"bytes"
@@ -39,6 +39,20 @@ func DefaultClientLoggingConfig() *LoggingConfig {
 	}
 }
 
+func New() *LoggingConfig {
+	return &LoggingConfig{}
+}
+
+func (lc *LoggingConfig) NoTrace() *LoggingConfig {
+	lc.ExcludeTrace = true
+	return lc
+}
+
+func (lc *LoggingConfig) Root(configure func(sink *SinkConfig) *SinkConfig) *LoggingConfig {
+	lc.RootSink = configure(Sink())
+	return lc
+}
+
 // Returns the TOML for a top-level logging config wrapped with [logging]
 func (lc *LoggingConfig) RootTOMLString() string {
 	return TOMLString(LoggingConfigWrapper{lc})
diff --git a/logging/config/config_test.go b/logging/logconfig/config_test.go
similarity index 97%
rename from logging/config/config_test.go
rename to logging/logconfig/config_test.go
index 089710aa..af0c3a5e 100644
--- a/logging/config/config_test.go
+++ b/logging/logconfig/config_test.go
@@ -1,4 +1,4 @@
-package config
+package logconfig
 
 import (
 	"testing"
diff --git a/logging/config/filter.go b/logging/logconfig/filter.go
similarity index 99%
rename from logging/config/filter.go
rename to logging/logconfig/filter.go
index d4d4aede..a048ebc8 100644
--- a/logging/config/filter.go
+++ b/logging/logconfig/filter.go
@@ -1,4 +1,4 @@
-package config
+package logconfig
 
 import (
 	"fmt"
diff --git a/logging/config/filter_test.go b/logging/logconfig/filter_test.go
similarity index 99%
rename from logging/config/filter_test.go
rename to logging/logconfig/filter_test.go
index 9602fa71..967d0c0d 100644
--- a/logging/config/filter_test.go
+++ b/logging/logconfig/filter_test.go
@@ -1,4 +1,4 @@
-package config
+package logconfig
 
 import (
 	"testing"
diff --git a/logging/config/presets/instructions.go b/logging/logconfig/presets/instructions.go
similarity index 66%
rename from logging/config/presets/instructions.go
rename to logging/logconfig/presets/instructions.go
index 91065d2f..6bc4c4f7 100644
--- a/logging/config/presets/instructions.go
+++ b/logging/logconfig/presets/instructions.go
@@ -3,7 +3,7 @@ package presets
 import (
 	"fmt"
 
-	"github.com/hyperledger/burrow/logging/config"
+	"github.com/hyperledger/burrow/logging/logconfig"
 	"github.com/hyperledger/burrow/logging/loggers"
 	"github.com/hyperledger/burrow/logging/structure"
 )
@@ -20,7 +20,7 @@ type Instruction struct {
 	// by mutating the sink at the top of the stack and may move the cursor or by pushing child sinks
 	// to the stack. The builder may also return a modified ops slice whereby it may insert Instruction calls
 	// acting as a macro or consume ops as arguments.
-	builder func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error)
+	builder func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error)
 }
 
 func (i Instruction) Name() string {
@@ -48,26 +48,26 @@ var instructions = []Instruction{
 	{
 		name: Up,
 		desc: "Ascend the sink tree by travelling up the stack to the previous sink recorded on the stack",
-		builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) {
+		builder: func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error) {
 			return pop(stack), nil
 		},
 	},
 	{
 		name: Down,
 		desc: "Descend the sink tree by inserting a sink as a child to the current sink and adding it to the stack",
-		builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) {
-			return push(stack, config.Sink()), nil
+		builder: func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error) {
+			return push(stack, logconfig.Sink()), nil
 		},
 	},
 	{
 		name: Minimal,
 		desc: "A generally less chatty log output, follow with output options",
-		builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) {
+		builder: func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error) {
 			return push(stack,
-				config.Sink().SetTransform(config.PruneTransform(structure.TraceKey, structure.RunId)),
-				config.Sink().SetTransform(config.FilterTransform(config.IncludeWhenAllMatch,
+				logconfig.Sink().SetTransform(logconfig.PruneTransform(structure.TraceKey, structure.RunId)),
+				logconfig.Sink().SetTransform(logconfig.FilterTransform(logconfig.IncludeWhenAllMatch,
 					structure.ChannelKey, structure.InfoChannelName)),
-				config.Sink().SetTransform(config.FilterTransform(config.ExcludeWhenAnyMatches,
+				logconfig.Sink().SetTransform(logconfig.FilterTransform(logconfig.ExcludeWhenAnyMatches,
 					structure.ComponentKey, "Tendermint",
 					"module", "p2p",
 					"module", "mempool"))), nil
@@ -76,17 +76,17 @@ var instructions = []Instruction{
 	{
 		name: IncludeAny,
 		desc: "Establish an 'include when any predicate matches' filter transform at this this sink",
-		builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) {
+		builder: func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error) {
 			sink := peek(stack)
 			ensureFilter(sink)
-			sink.Transform.FilterConfig.FilterMode = config.IncludeWhenAnyMatches
+			sink.Transform.FilterConfig.FilterMode = logconfig.IncludeWhenAnyMatches
 			return stack, nil
 		},
 	},
 	{
 		name: Info,
 		desc: "Add a filter predicate to match the Info logging channel",
-		builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) {
+		builder: func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error) {
 			sink := peek(stack)
 			ensureFilter(sink)
 			sink.Transform.FilterConfig.AddPredicate(structure.ChannelKey, structure.InfoChannelName)
@@ -96,27 +96,27 @@ var instructions = []Instruction{
 	{
 		name: Stdout,
 		desc: "Use Stdout output for this sink",
-		builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) {
+		builder: func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error) {
 			sink := peek(stack)
 			ensureOutput(sink)
-			sink.Output.OutputType = config.Stdout
+			sink.Output.OutputType = logconfig.Stdout
 			return stack, nil
 		},
 	},
 	{
 		name: Stderr,
 		desc: "Use Stderr output for this sink",
-		builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) {
+		builder: func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error) {
 			sink := peek(stack)
 			ensureOutput(sink)
-			sink.Output.OutputType = config.Stderr
+			sink.Output.OutputType = logconfig.Stderr
 			return stack, nil
 		},
 	},
 	{
 		name: Terminal,
 		desc: "Use the the terminal output format for this sink",
-		builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) {
+		builder: func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error) {
 			sink := peek(stack)
 			ensureOutput(sink)
 			sink.Output.Format = loggers.TerminalFormat
@@ -126,7 +126,7 @@ var instructions = []Instruction{
 	{
 		name: JSON,
 		desc: "Use the the terminal output format for this sink",
-		builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) {
+		builder: func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error) {
 			sink := peek(stack)
 			ensureOutput(sink)
 			sink.Output.Format = loggers.JSONFormat
@@ -137,11 +137,11 @@ var instructions = []Instruction{
 		name:  File,
 		desc:  "Use the the terminal output format for this sink",
 		nargs: 1,
-		builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) {
+		builder: func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error) {
 			sink := peek(stack)
 			ensureOutput(sink)
-			sink.Output.OutputType = config.File
-			sink.Output.FileConfig = &config.FileConfig{
+			sink.Output.OutputType = logconfig.File
+			sink.Output.FileConfig = &logconfig.FileConfig{
 				Path: args[0],
 			}
 			return stack, nil
@@ -172,8 +172,8 @@ func Describe(name string) string {
 	return preset.desc
 }
 
-func BuildSinkConfig(ops ...string) (*config.SinkConfig, error) {
-	stack := []*config.SinkConfig{config.Sink()}
+func BuildSinkConfig(ops ...string) (*logconfig.SinkConfig, error) {
+	stack := []*logconfig.SinkConfig{logconfig.Sink()}
 	var err error
 	pos := 0
 	for len(ops) > 0 {
@@ -199,24 +199,24 @@ func BuildSinkConfig(ops ...string) (*config.SinkConfig, error) {
 	return stack[0], nil
 }
 
-func ensureFilter(sinkConfig *config.SinkConfig) {
+func ensureFilter(sinkConfig *logconfig.SinkConfig) {
 	if sinkConfig.Transform == nil {
-		sinkConfig.Transform = &config.TransformConfig{}
+		sinkConfig.Transform = &logconfig.TransformConfig{}
 	}
 	if sinkConfig.Transform.FilterConfig == nil {
-		sinkConfig.Transform.FilterConfig = &config.FilterConfig{}
+		sinkConfig.Transform.FilterConfig = &logconfig.FilterConfig{}
 	}
-	sinkConfig.Transform.TransformType = config.Filter
+	sinkConfig.Transform.TransformType = logconfig.Filter
 }
 
-func ensureOutput(sinkConfig *config.SinkConfig) {
+func ensureOutput(sinkConfig *logconfig.SinkConfig) {
 	if sinkConfig.Output == nil {
-		sinkConfig.Output = &config.OutputConfig{}
+		sinkConfig.Output = &logconfig.OutputConfig{}
 	}
 }
 
 // Push a path sequence of sinks onto the stack
-func push(stack []*config.SinkConfig, sinkConfigs ...*config.SinkConfig) []*config.SinkConfig {
+func push(stack []*logconfig.SinkConfig, sinkConfigs ...*logconfig.SinkConfig) []*logconfig.SinkConfig {
 	for _, sinkConfig := range sinkConfigs {
 		peek(stack).AddSinks(sinkConfig)
 		stack = append(stack, sinkConfig)
@@ -224,10 +224,10 @@ func push(stack []*config.SinkConfig, sinkConfigs ...*config.SinkConfig) []*conf
 	return stack
 }
 
-func pop(stack []*config.SinkConfig) []*config.SinkConfig {
+func pop(stack []*logconfig.SinkConfig) []*logconfig.SinkConfig {
 	return stack[:len(stack)-1]
 }
 
-func peek(stack []*config.SinkConfig) *config.SinkConfig {
+func peek(stack []*logconfig.SinkConfig) *logconfig.SinkConfig {
 	return stack[len(stack)-1]
 }
diff --git a/logging/logconfig/presets/instructions_test.go b/logging/logconfig/presets/instructions_test.go
new file mode 100644
index 00000000..7cd1adb1
--- /dev/null
+++ b/logging/logconfig/presets/instructions_test.go
@@ -0,0 +1,51 @@
+package presets
+
+import (
+	"testing"
+
+	"github.com/hyperledger/burrow/logging/logconfig"
+	"github.com/hyperledger/burrow/logging/loggers"
+	"github.com/hyperledger/burrow/logging/structure"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+func TestBuildSinkConfig(t *testing.T) {
+	builtSink, err := BuildSinkConfig(IncludeAny, Info, Stdout, Terminal, Down, Down, Info, Stdout, Up, Info, Stderr)
+	require.NoError(t, err)
+	expectedSink := logconfig.Sink().
+		SetTransform(logconfig.FilterTransform(logconfig.IncludeWhenAnyMatches,
+			structure.ChannelKey, structure.InfoChannelName)).SetOutput(logconfig.StdoutOutput().SetFormat(loggers.TerminalFormat)).AddSinks(
+		logconfig.Sink().SetTransform(logconfig.FilterTransform(logconfig.NoFilterMode,
+			structure.ChannelKey, structure.InfoChannelName)).SetOutput(logconfig.StderrOutput()).AddSinks(
+			logconfig.Sink().SetTransform(logconfig.FilterTransform(logconfig.NoFilterMode,
+				structure.ChannelKey, structure.InfoChannelName)).SetOutput(logconfig.StdoutOutput())))
+
+	//fmt.Println(config.JSONString(expectedSink), "\n", config.JSONString(builtSink))
+	assert.Equal(t, logconfig.JSONString(expectedSink), logconfig.JSONString(builtSink))
+}
+
+func TestMinimalPreset(t *testing.T) {
+	builtSink, err := BuildSinkConfig(Minimal, Stderr)
+	require.NoError(t, err)
+	expectedSink := logconfig.Sink().
+		AddSinks(logconfig.Sink().SetTransform(logconfig.PruneTransform(structure.TraceKey, structure.RunId)).
+			AddSinks(logconfig.Sink().SetTransform(logconfig.FilterTransform(logconfig.IncludeWhenAllMatch,
+				structure.ChannelKey, structure.InfoChannelName)).
+				AddSinks(logconfig.Sink().SetTransform(logconfig.FilterTransform(logconfig.ExcludeWhenAnyMatches,
+					structure.ComponentKey, "Tendermint",
+					"module", "p2p",
+					"module", "mempool")).SetOutput(logconfig.StderrOutput()))))
+	//fmt.Println(config.TOMLString(expectedSink), "\n", config.TOMLString(builtSink))
+	assert.Equal(t, logconfig.TOMLString(expectedSink), logconfig.TOMLString(builtSink))
+}
+
+func TestFileOutput(t *testing.T) {
+	path := "foo.log"
+	builtSink, err := BuildSinkConfig(Down, File, path, JSON)
+	require.NoError(t, err)
+	expectedSink := logconfig.Sink().
+		AddSinks(logconfig.Sink().SetOutput(logconfig.FileOutput(path).SetFormat(loggers.JSONFormat)))
+	//fmt.Println(config.TOMLString(expectedSink), "\n", config.TOMLString(builtSink))
+	assert.Equal(t, logconfig.TOMLString(expectedSink), logconfig.TOMLString(builtSink))
+}
diff --git a/logging/config/sinks.go b/logging/logconfig/sinks.go
similarity index 97%
rename from logging/config/sinks.go
rename to logging/logconfig/sinks.go
index aa30a69e..e323fdab 100644
--- a/logging/config/sinks.go
+++ b/logging/logconfig/sinks.go
@@ -1,4 +1,4 @@
-package config
+package logconfig
 
 import (
 	"fmt"
@@ -236,14 +236,17 @@ func PruneTransform(keys ...string) *TransformConfig {
 	}
 }
 
-func FilterTransform(fmode filterMode, keyvalueRegexes ...string) *TransformConfig {
-	length := len(keyvalueRegexes) / 2
+func FilterTransform(fmode filterMode, keyValueRegexes ...string) *TransformConfig {
+	if len(keyValueRegexes)%2 == 1 {
+		keyValueRegexes = append(keyValueRegexes, "")
+	}
+	length := len(keyValueRegexes) / 2
 	predicates := make([]*KeyValuePredicateConfig, length)
 	for i := 0; i < length; i++ {
 		kv := i * 2
 		predicates[i] = &KeyValuePredicateConfig{
-			KeyRegex:   keyvalueRegexes[kv],
-			ValueRegex: keyvalueRegexes[kv+1],
+			KeyRegex:   keyValueRegexes[kv],
+			ValueRegex: keyValueRegexes[kv+1],
 		}
 	}
 	return &TransformConfig{
diff --git a/logging/config/sinks_test.go b/logging/logconfig/sinks_test.go
similarity index 99%
rename from logging/config/sinks_test.go
rename to logging/logconfig/sinks_test.go
index ba722a9d..8eba2628 100644
--- a/logging/config/sinks_test.go
+++ b/logging/logconfig/sinks_test.go
@@ -1,4 +1,4 @@
-package config
+package logconfig
 
 import (
 	"encoding/json"
diff --git a/logging/logconfig/sort.go b/logging/logconfig/sort.go
new file mode 100644
index 00000000..6b6aa674
--- /dev/null
+++ b/logging/logconfig/sort.go
@@ -0,0 +1 @@
+package logconfig
diff --git a/logging/loggers/burrow_format_logger.go b/logging/loggers/burrow_format_logger.go
index f32d0933..1a8070bf 100644
--- a/logging/loggers/burrow_format_logger.go
+++ b/logging/loggers/burrow_format_logger.go
@@ -20,6 +20,7 @@ import (
 
 	kitlog "github.com/go-kit/kit/log"
 	"github.com/hyperledger/burrow/logging/structure"
+	"github.com/tmthrgd/go-hex"
 )
 
 // Logger that implements some formatting conventions for burrow and burrow-client
@@ -48,7 +49,7 @@ func (bfl *burrowFormatLogger) Log(keyvals ...interface{}) error {
 			case fmt.Stringer:
 				value = v.String()
 			case []byte:
-				value = fmt.Sprintf("%X", v)
+				value = hex.EncodeUpperToString(v)
 			case time.Time:
 				value = v.Format(time.RFC3339Nano)
 			}
diff --git a/permission/account_permissions.go b/permission/account_permissions.go
index 6de0a443..fdc30427 100644
--- a/permission/account_permissions.go
+++ b/permission/account_permissions.go
@@ -2,6 +2,19 @@ package permission
 
 import "github.com/hyperledger/burrow/binary"
 
+func NewAccountPermissions(pss ...PermFlag) AccountPermissions {
+	var perms PermFlag
+	for _, ps := range pss {
+		perms |= ps
+	}
+	return AccountPermissions{
+		Base: BasePermissions{
+			Perms:  perms,
+			SetBit: perms,
+		},
+	}
+}
+
 // Returns true if the role is found
 func (ap AccountPermissions) HasRole(role string) bool {
 	role = string(binary.RightPadBytes([]byte(role), 32))
diff --git a/permission/util.go b/permission/util.go
index 6f4ba1eb..0436f939 100644
--- a/permission/util.go
+++ b/permission/util.go
@@ -15,7 +15,6 @@
 package permission
 
 import (
-	"fmt"
 	"strings"
 )
 
@@ -83,40 +82,28 @@ func PermFlagFromStringList(permissions []string) (PermFlag, error) {
 
 // Builds a list of set permissions from a BasePermission by creating a list of permissions strings
 // from the resultant permissions of basePermissions
-func BasePermissionsToStringList(basePermissions BasePermissions) ([]string, error) {
+func BasePermissionsToStringList(basePermissions BasePermissions) []string {
 	return PermFlagToStringList(basePermissions.ResultantPerms())
 }
 
 // Creates a list of individual permission flag strings from a possibly composite PermFlag
 // by projecting out each bit and adding its permission string if it is set
-func PermFlagToStringList(permFlag PermFlag) ([]string, error) {
+func PermFlagToStringList(permFlag PermFlag) []string {
 	permStrings := make([]string, 0, NumPermissions)
-	if permFlag > AllPermFlags {
-		return nil, fmt.Errorf("resultant permission 0b%b is invalid: has permission flag set above top flag 0b%b",
-			permFlag, TopPermFlag)
-	}
 	for i := uint(0); i < NumPermissions; i++ {
 		permFlag := permFlag & (1 << i)
 		if permFlag > 0 {
 			permStrings = append(permStrings, permFlag.String())
 		}
 	}
-	return permStrings, nil
+	return permStrings
 }
 
 // Generates a human readable string from the resultant permissions of basePermission
 func BasePermissionsString(basePermissions BasePermissions) string {
-	permStrings, err := BasePermissionsToStringList(basePermissions)
-	if err != nil {
-		return UnknownString
-	}
-	return strings.Join(permStrings, " | ")
+	return strings.Join(BasePermissionsToStringList(basePermissions), " | ")
 }
 
 func String(permFlag PermFlag) string {
-	permStrings, err := PermFlagToStringList(permFlag)
-	if err != nil {
-		return UnknownString
-	}
-	return strings.Join(permStrings, " | ")
+	return strings.Join(PermFlagToStringList(permFlag), " | ")
 }
diff --git a/permission/util_test.go b/permission/util_test.go
index 10553612..86f0ed62 100644
--- a/permission/util_test.go
+++ b/permission/util_test.go
@@ -25,17 +25,15 @@ func TestBasePermissionsFromStringList(t *testing.T) {
 }
 
 func TestBasePermissionsToStringList(t *testing.T) {
-	permStrings, err := BasePermissionsToStringList(allSetBasePermission(Root | HasRole | SetBase | Call))
-	require.NoError(t, err)
+	permStrings := BasePermissionsToStringList(allSetBasePermission(Root | HasRole | SetBase | Call))
 	assert.Equal(t, []string{"root", "call", "setBase", "hasRole"}, permStrings)
 
-	permStrings, err = BasePermissionsToStringList(allSetBasePermission(AllPermFlags))
-	require.NoError(t, err)
+	permStrings = BasePermissionsToStringList(allSetBasePermission(AllPermFlags))
 	assert.Equal(t, []string{"root", "send", "call", "createContract", "createAccount", "bond", "name", "hasBase",
 		"setBase", "unsetBase", "setGlobal", "hasRole", "addRole", "removeRole"}, permStrings)
 
-	permStrings, err = BasePermissionsToStringList(allSetBasePermission(AllPermFlags + 1))
-	assert.Error(t, err)
+	permStrings = BasePermissionsToStringList(allSetBasePermission(AllPermFlags + 1))
+	assert.Equal(t, []string{}, permStrings)
 }
 
 func TestBasePermissionsString(t *testing.T) {
diff --git a/protobuf/acm.proto b/protobuf/acm.proto
index 8a52a277..1fef3bd9 100644
--- a/protobuf/acm.proto
+++ b/protobuf/acm.proto
@@ -9,15 +9,10 @@ import "github.com/gogo/protobuf/gogoproto/gogo.proto";
 import "permission.proto";
 import "crypto.proto";
 
-// Enable custom Marshal method.
 option (gogoproto.marshaler_all) = true;
-// Enable custom Unmarshal method.
 option (gogoproto.unmarshaler_all) = true;
-// Enable custom Size method (Required by Marshal and Unmarshal).
 option (gogoproto.sizer_all) = true;
-// Enable registration with golang/protobuf for the grpc-gateway.
 option (gogoproto.goproto_registration) = true;
-// Enable generation of XXX_MessageName methods for grpc-go/status.
 option (gogoproto.messagename_all) = true;
 
 message ConcreteAccount {
@@ -28,4 +23,4 @@ message ConcreteAccount {
     uint64 Balance = 4;
     bytes Code = 5 [(gogoproto.customtype) = "Bytecode", (gogoproto.nullable) = false];
     permission.AccountPermissions Permissions = 6 [(gogoproto.nullable) = false];
-}
\ No newline at end of file
+}
diff --git a/protobuf/balance.proto b/protobuf/balance.proto
new file mode 100644
index 00000000..ea71f6c4
--- /dev/null
+++ b/protobuf/balance.proto
@@ -0,0 +1,20 @@
+// Needed to proto2 rather than proto3 to get pointer field for PermArg
+syntax = 'proto3';
+
+option go_package = "github.com/hyperledger/burrow/acm/balance";
+
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+package balance;
+
+option (gogoproto.marshaler_all) = true;
+option (gogoproto.unmarshaler_all) = true;
+option (gogoproto.sizer_all) = true;
+option (gogoproto.goproto_registration) = true;
+option (gogoproto.messagename_all) = true;
+
+message Balance {
+    option (gogoproto.goproto_stringer) = false;
+    uint32 Type = 1 [(gogoproto.casttype) = "Type"];
+    uint64 Amount = 2;
+}
\ No newline at end of file
diff --git a/protobuf/exec.proto b/protobuf/exec.proto
index 172f540b..fde24149 100644
--- a/protobuf/exec.proto
+++ b/protobuf/exec.proto
@@ -5,7 +5,7 @@ package exec;
 option go_package = "github.com/hyperledger/burrow/execution/exec";
 
 import "github.com/gogo/protobuf/gogoproto/gogo.proto";
-import "github.com/tendermint/tendermint/abci/types/types.proto";
+//import "github.com/tendermint/tendermint/abci/types/types.proto";
 
 import "errors.proto";
 import "names.proto";
diff --git a/protobuf/payload.proto b/protobuf/payload.proto
index 1e75fdf4..55938021 100644
--- a/protobuf/payload.proto
+++ b/protobuf/payload.proto
@@ -20,12 +20,14 @@ option (gogoproto.goproto_registration) = true;
 // Enable generation of XXX_MessageName methods for grpc-go/status.
 option (gogoproto.messagename_all) = true;
 
-message AnyPayload {
+message Any {
     CallTx CallTx = 1;
     SendTx SendTx = 2;
     NameTx NameTx = 3;
-    PermissionsTx PermissionsTx = 4;
-    GovernanceTx GovernanceTx = 5;
+    PermsTx PermsTx = 4;
+    GovTx GovTx = 5;
+    BondTx BondTx = 6;
+    UnbondTx UnbondTx = 7;
 }
 
 // An input to a transaction that may carry an Amount as a charge and whose sequence number must be one greater than
@@ -76,7 +78,7 @@ message SendTx {
 }
 
 // An update to the on-chain permissions
-message PermissionsTx {
+message PermsTx {
     option (gogoproto.goproto_stringer) = false;
     // The permission moderator
     TxInput Input = 1;
@@ -114,7 +116,7 @@ message UnbondTx {
     uint64 Height = 3;
 }
 
-message GovernanceTx {
+message GovTx {
     option (gogoproto.goproto_stringer) = false;
     option (gogoproto.goproto_getters) = false;
 
diff --git a/protobuf/rpcquery.proto b/protobuf/rpcquery.proto
index bbb51225..fc8b6626 100644
--- a/protobuf/rpcquery.proto
+++ b/protobuf/rpcquery.proto
@@ -8,6 +8,7 @@ import "github.com/gogo/protobuf/gogoproto/gogo.proto";
 
 import "names.proto";
 import "acm.proto";
+import "validator.proto";
 
 option (gogoproto.marshaler_all) = true;
 option (gogoproto.unmarshaler_all) = true;
@@ -20,6 +21,7 @@ service Query {
     rpc ListAccounts (ListAccountsParam) returns (stream acm.ConcreteAccount);
     rpc GetName (GetNameParam) returns (names.Entry);
     rpc ListNames (ListNamesParam) returns (stream names.Entry);
+    rpc GetValidatorSet (GetValidatorSetParam) returns (ValidatorSet);
 }
 
 message GetAccountParam {
@@ -38,3 +40,16 @@ message ListNamesParam {
     string Query = 1;
 }
 
+message GetValidatorSetParam {
+    bool IncludeHistory = 1;
+}
+
+message ValidatorSet {
+    uint64 height = 1;
+    repeated validator.Validator Set = 2;
+    repeated ValidatorSetDeltas History = 3;
+}
+
+message ValidatorSetDeltas {
+    repeated validator.Validator Validators = 2;
+}
\ No newline at end of file
diff --git a/protobuf/rpctransact.proto b/protobuf/rpctransact.proto
index b2753a17..64b77821 100644
--- a/protobuf/rpctransact.proto
+++ b/protobuf/rpctransact.proto
@@ -32,7 +32,7 @@ service Transact {
     // Sign transaction server-side
     rpc SignTx (TxEnvelopeParam) returns (TxEnvelope);
     // Formulate a transaction from a Payload and retrun the envelop with the Tx bytes ready to sign
-    rpc FormulateTx (PayloadParam) returns (TxEnvelope);
+    rpc FormulateTx (payload.Any) returns (TxEnvelope);
 
     // Formulate and sign a CallTx transaction signed server-side and wait for it to be included in a block, retrieving response
     rpc CallTxSync (payload.CallTx) returns (exec.TxExecution);
@@ -61,12 +61,6 @@ message CallCodeParam {
     bytes Data = 3;
 }
 
-message PayloadParam {
-    payload.CallTx CallTx = 1;
-    payload.SendTx SendTx = 2;
-    payload.NameTx NameTx = 3;
-}
-
 message TxEnvelope {
     txs.Envelope Envelope = 1 [(gogoproto.customtype) = "github.com/hyperledger/burrow/txs.Envelope"];
 }
@@ -75,6 +69,6 @@ message TxEnvelopeParam {
     // An existing Envelope - either signed or unsigned - if the latter will be signed server-side
     txs.Envelope Envelope = 1 [(gogoproto.customtype) = "github.com/hyperledger/burrow/txs.Envelope"];
     // If no Envelope provided then one will be generated from the provided payload and signed server-side
-    PayloadParam Payload = 2;
+    payload.Any Payload = 2;
 }
 
diff --git a/protobuf/spec.proto b/protobuf/spec.proto
index 7f0c6abe..03a2090b 100644
--- a/protobuf/spec.proto
+++ b/protobuf/spec.proto
@@ -1,35 +1,28 @@
 // Needed to proto2 rather than proto3 to get pointer field for PermArg
-syntax = 'proto2';
+syntax = 'proto3';
 
 option go_package = "github.com/hyperledger/burrow/genesis/spec";
 
 import "github.com/gogo/protobuf/gogoproto/gogo.proto";
 
 import "crypto.proto";
+import "balance.proto";
 
 package spec;
 
-// Enable custom Marshal method.
 option (gogoproto.marshaler_all) = true;
-// Enable custom Unmarshal method.
 option (gogoproto.unmarshaler_all) = true;
-// Enable custom Size method (Required by Marshal and Unmarshal).
 option (gogoproto.sizer_all) = true;
-// Enable registration with golang/protobuf for the grpc-gateway.
 option (gogoproto.goproto_registration) = true;
-// Enable generation of XXX_MessageName methods for grpc-go/status.
 option (gogoproto.messagename_all) = true;
 
 message TemplateAccount {
-    option (gogoproto.goproto_unrecognized) = false;
-
-    optional string Name = 1 [(gogoproto.nullable) = false];
-    optional bytes Address = 2 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""];
-    optional bytes NodeAddress = 3 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""];
-    optional crypto.PublicKey PublicKey = 4 [(gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""];
-    optional uint64 Amount = 5 [(gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""];
-    optional uint64 Power = 6 [(gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""];
-    repeated string Permissions = 7 [(gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""];
-    repeated string Roles = 8 [(gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""];
+    string Name = 1;
+    bytes Address = 2 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""];
+    bytes NodeAddress = 3 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""];
+    crypto.PublicKey PublicKey = 4 [(gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""];
+    repeated balance.Balance Amounts = 5 [(gogoproto.nullable) = false, (gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""];
+    repeated string Permissions = 6 [(gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""];
+    repeated string Roles = 7 [(gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""];
 }
 
diff --git a/protobuf/validator.proto b/protobuf/validator.proto
new file mode 100644
index 00000000..dc621ab7
--- /dev/null
+++ b/protobuf/validator.proto
@@ -0,0 +1,22 @@
+syntax = 'proto3';
+
+package validator;
+
+option go_package = "github.com/hyperledger/burrow/acm/validator";
+
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+import "crypto.proto";
+
+option (gogoproto.marshaler_all) = true;
+option (gogoproto.unmarshaler_all) = true;
+option (gogoproto.sizer_all) = true;
+option (gogoproto.goproto_registration) = true;
+option (gogoproto.messagename_all) = true;
+
+message Validator {
+    option (gogoproto.goproto_stringer) = false;
+    bytes Address = 1 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address"];
+    crypto.PublicKey PublicKey = 2 [(gogoproto.nullable) = false];
+    uint64 Power = 3;
+}
diff --git a/rpc/result.go b/rpc/result.go
index af777d94..35d21892 100644
--- a/rpc/result.go
+++ b/rpc/result.go
@@ -18,6 +18,7 @@ import (
 	"time"
 
 	"github.com/hyperledger/burrow/acm"
+	"github.com/hyperledger/burrow/acm/validator"
 	"github.com/hyperledger/burrow/binary"
 	"github.com/hyperledger/burrow/crypto"
 	"github.com/hyperledger/burrow/execution/names"
@@ -96,7 +97,7 @@ func (b *Block) UnmarshalJSON(data []byte) (err error) {
 type ResultStatus struct {
 	NodeInfo          p2p.NodeInfo
 	GenesisHash       binary.HexBytes
-	PubKey            crypto.PublicKey
+	PublicKey         crypto.PublicKey
 	LatestBlockHash   binary.HexBytes
 	LatestBlockHeight uint64
 	LatestBlockTime   int64
@@ -130,6 +131,7 @@ type Peer struct {
 }
 
 type ResultNetInfo struct {
+	ThisNode  p2p.NodeInfo
 	Listening bool
 	Listeners []string
 	Peers     []*Peer
@@ -137,8 +139,8 @@ type ResultNetInfo struct {
 
 type ResultListValidators struct {
 	BlockHeight         uint64
-	BondedValidators    []*acm.ConcreteValidator
-	UnbondingValidators []*acm.ConcreteValidator
+	BondedValidators    []*validator.Validator
+	UnbondingValidators []*validator.Validator
 }
 
 type ResultDumpConsensusState struct {
diff --git a/rpc/rpcevents/execution_events_server.go b/rpc/rpcevents/execution_events_server.go
index 2b042c77..d8f48e14 100644
--- a/rpc/rpcevents/execution_events_server.go
+++ b/rpc/rpcevents/execution_events_server.go
@@ -7,7 +7,7 @@ import (
 	"io"
 
 	"github.com/gogo/protobuf/proto"
-	bcm "github.com/hyperledger/burrow/blockchain"
+	bcm "github.com/hyperledger/burrow/bcm"
 	"github.com/hyperledger/burrow/event"
 	"github.com/hyperledger/burrow/event/query"
 	"github.com/hyperledger/burrow/execution/exec"
@@ -29,12 +29,12 @@ type Provider interface {
 type executionEventsServer struct {
 	eventsProvider Provider
 	subscribable   event.Subscribable
-	tip            bcm.TipInfo
+	tip            bcm.BlockchainInfo
 	logger         *logging.Logger
 }
 
 func NewExecutionEventsServer(eventsProvider Provider, subscribable event.Subscribable,
-	tip bcm.TipInfo, logger *logging.Logger) ExecutionEventsServer {
+	tip bcm.BlockchainInfo, logger *logging.Logger) ExecutionEventsServer {
 
 	return &executionEventsServer{
 		eventsProvider: eventsProvider,
diff --git a/rpc/rpcquery/query_server.go b/rpc/rpcquery/query_server.go
index edcb968b..debdc05b 100644
--- a/rpc/rpcquery/query_server.go
+++ b/rpc/rpcquery/query_server.go
@@ -5,24 +5,36 @@ import (
 
 	"github.com/hyperledger/burrow/acm"
 	"github.com/hyperledger/burrow/acm/state"
+	"github.com/hyperledger/burrow/bcm"
+	"github.com/hyperledger/burrow/consensus/tendermint"
 	"github.com/hyperledger/burrow/event/query"
 	"github.com/hyperledger/burrow/execution/names"
+	"github.com/hyperledger/burrow/logging"
 )
 
 type queryServer struct {
-	accounts state.IterableReader
-	nameReg  names.IterableReader
+	accounts   state.IterableReader
+	nameReg    names.IterableReader
+	blockchain bcm.BlockchainInfo
+	nodeView   *tendermint.NodeView
+	logger     *logging.Logger
 }
 
 var _ QueryServer = &queryServer{}
 
-func NewQueryServer(state state.IterableReader, nameReg names.IterableReader) *queryServer {
+func NewQueryServer(state state.IterableReader, nameReg names.IterableReader, blockchain bcm.BlockchainInfo,
+	nodeView *tendermint.NodeView, logger *logging.Logger) *queryServer {
 	return &queryServer{
-		accounts: state,
-		nameReg:  nameReg,
+		accounts:   state,
+		nameReg:    nameReg,
+		blockchain: blockchain,
+		nodeView:   nodeView,
+		logger:     logger,
 	}
 }
 
+// Account state
+
 func (qs *queryServer) GetAccount(ctx context.Context, param *GetAccountParam) (*acm.ConcreteAccount, error) {
 	acc, err := qs.accounts.GetAccount(param.Address)
 	if err != nil {
@@ -74,3 +86,20 @@ func (qs *queryServer) ListNames(param *ListNamesParam, stream Query_ListNamesSe
 	}
 	return streamErr
 }
+
+func (qs *queryServer) GetValidatorSet(ctx context.Context, param *GetValidatorSetParam) (*ValidatorSet, error) {
+	set, deltas, height := qs.blockchain.ValidatorsHistory()
+	vs := &ValidatorSet{
+		Height: height,
+		Set:    set.Validators(),
+	}
+	if param.IncludeHistory {
+		vs.History = make([]*ValidatorSetDeltas, len(deltas))
+		for i, d := range deltas {
+			vs.History[i] = &ValidatorSetDeltas{
+				Validators: d.Validators(),
+			}
+		}
+	}
+	return vs, nil
+}
diff --git a/rpc/rpcquery/rpcquery.pb.go b/rpc/rpcquery/rpcquery.pb.go
index ce9b9f17..ec9b8171 100644
--- a/rpc/rpcquery/rpcquery.pb.go
+++ b/rpc/rpcquery/rpcquery.pb.go
@@ -12,6 +12,9 @@
 		ListAccountsParam
 		GetNameParam
 		ListNamesParam
+		GetValidatorSetParam
+		ValidatorSet
+		ValidatorSetDeltas
 */
 package rpcquery
 
@@ -22,6 +25,7 @@ import math "math"
 import _ "github.com/gogo/protobuf/gogoproto"
 import names "github.com/hyperledger/burrow/execution/names"
 import acm "github.com/hyperledger/burrow/acm"
+import validator "github.com/hyperledger/burrow/acm/validator"
 
 import github_com_hyperledger_burrow_crypto "github.com/hyperledger/burrow/crypto"
 
@@ -114,6 +118,82 @@ func (m *ListNamesParam) GetQuery() string {
 func (*ListNamesParam) XXX_MessageName() string {
 	return "rpcquery.ListNamesParam"
 }
+
+type GetValidatorSetParam struct {
+	IncludeHistory bool `protobuf:"varint,1,opt,name=IncludeHistory,proto3" json:"IncludeHistory,omitempty"`
+}
+
+func (m *GetValidatorSetParam) Reset()                    { *m = GetValidatorSetParam{} }
+func (m *GetValidatorSetParam) String() string            { return proto.CompactTextString(m) }
+func (*GetValidatorSetParam) ProtoMessage()               {}
+func (*GetValidatorSetParam) Descriptor() ([]byte, []int) { return fileDescriptorRpcquery, []int{4} }
+
+func (m *GetValidatorSetParam) GetIncludeHistory() bool {
+	if m != nil {
+		return m.IncludeHistory
+	}
+	return false
+}
+
+func (*GetValidatorSetParam) XXX_MessageName() string {
+	return "rpcquery.GetValidatorSetParam"
+}
+
+type ValidatorSet struct {
+	Height  uint64                 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"`
+	Set     []*validator.Validator `protobuf:"bytes,2,rep,name=Set" json:"Set,omitempty"`
+	History []*ValidatorSetDeltas  `protobuf:"bytes,3,rep,name=History" json:"History,omitempty"`
+}
+
+func (m *ValidatorSet) Reset()                    { *m = ValidatorSet{} }
+func (m *ValidatorSet) String() string            { return proto.CompactTextString(m) }
+func (*ValidatorSet) ProtoMessage()               {}
+func (*ValidatorSet) Descriptor() ([]byte, []int) { return fileDescriptorRpcquery, []int{5} }
+
+func (m *ValidatorSet) GetHeight() uint64 {
+	if m != nil {
+		return m.Height
+	}
+	return 0
+}
+
+func (m *ValidatorSet) GetSet() []*validator.Validator {
+	if m != nil {
+		return m.Set
+	}
+	return nil
+}
+
+func (m *ValidatorSet) GetHistory() []*ValidatorSetDeltas {
+	if m != nil {
+		return m.History
+	}
+	return nil
+}
+
+func (*ValidatorSet) XXX_MessageName() string {
+	return "rpcquery.ValidatorSet"
+}
+
+type ValidatorSetDeltas struct {
+	Validators []*validator.Validator `protobuf:"bytes,2,rep,name=Validators" json:"Validators,omitempty"`
+}
+
+func (m *ValidatorSetDeltas) Reset()                    { *m = ValidatorSetDeltas{} }
+func (m *ValidatorSetDeltas) String() string            { return proto.CompactTextString(m) }
+func (*ValidatorSetDeltas) ProtoMessage()               {}
+func (*ValidatorSetDeltas) Descriptor() ([]byte, []int) { return fileDescriptorRpcquery, []int{6} }
+
+func (m *ValidatorSetDeltas) GetValidators() []*validator.Validator {
+	if m != nil {
+		return m.Validators
+	}
+	return nil
+}
+
+func (*ValidatorSetDeltas) XXX_MessageName() string {
+	return "rpcquery.ValidatorSetDeltas"
+}
 func init() {
 	proto.RegisterType((*GetAccountParam)(nil), "rpcquery.GetAccountParam")
 	golang_proto.RegisterType((*GetAccountParam)(nil), "rpcquery.GetAccountParam")
@@ -123,6 +203,12 @@ func init() {
 	golang_proto.RegisterType((*GetNameParam)(nil), "rpcquery.GetNameParam")
 	proto.RegisterType((*ListNamesParam)(nil), "rpcquery.ListNamesParam")
 	golang_proto.RegisterType((*ListNamesParam)(nil), "rpcquery.ListNamesParam")
+	proto.RegisterType((*GetValidatorSetParam)(nil), "rpcquery.GetValidatorSetParam")
+	golang_proto.RegisterType((*GetValidatorSetParam)(nil), "rpcquery.GetValidatorSetParam")
+	proto.RegisterType((*ValidatorSet)(nil), "rpcquery.ValidatorSet")
+	golang_proto.RegisterType((*ValidatorSet)(nil), "rpcquery.ValidatorSet")
+	proto.RegisterType((*ValidatorSetDeltas)(nil), "rpcquery.ValidatorSetDeltas")
+	golang_proto.RegisterType((*ValidatorSetDeltas)(nil), "rpcquery.ValidatorSetDeltas")
 }
 
 // Reference imports to suppress errors if they are not otherwise used.
@@ -140,6 +226,7 @@ type QueryClient interface {
 	ListAccounts(ctx context.Context, in *ListAccountsParam, opts ...grpc.CallOption) (Query_ListAccountsClient, error)
 	GetName(ctx context.Context, in *GetNameParam, opts ...grpc.CallOption) (*names.Entry, error)
 	ListNames(ctx context.Context, in *ListNamesParam, opts ...grpc.CallOption) (Query_ListNamesClient, error)
+	GetValidatorSet(ctx context.Context, in *GetValidatorSetParam, opts ...grpc.CallOption) (*ValidatorSet, error)
 }
 
 type queryClient struct {
@@ -232,6 +319,15 @@ func (x *queryListNamesClient) Recv() (*names.Entry, error) {
 	return m, nil
 }
 
+func (c *queryClient) GetValidatorSet(ctx context.Context, in *GetValidatorSetParam, opts ...grpc.CallOption) (*ValidatorSet, error) {
+	out := new(ValidatorSet)
+	err := grpc.Invoke(ctx, "/rpcquery.Query/GetValidatorSet", in, out, c.cc, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
 // Server API for Query service
 
 type QueryServer interface {
@@ -239,6 +335,7 @@ type QueryServer interface {
 	ListAccounts(*ListAccountsParam, Query_ListAccountsServer) error
 	GetName(context.Context, *GetNameParam) (*names.Entry, error)
 	ListNames(*ListNamesParam, Query_ListNamesServer) error
+	GetValidatorSet(context.Context, *GetValidatorSetParam) (*ValidatorSet, error)
 }
 
 func RegisterQueryServer(s *grpc.Server, srv QueryServer) {
@@ -323,6 +420,24 @@ func (x *queryListNamesServer) Send(m *names.Entry) error {
 	return x.ServerStream.SendMsg(m)
 }
 
+func _Query_GetValidatorSet_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(GetValidatorSetParam)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(QueryServer).GetValidatorSet(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/rpcquery.Query/GetValidatorSet",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(QueryServer).GetValidatorSet(ctx, req.(*GetValidatorSetParam))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
 var _Query_serviceDesc = grpc.ServiceDesc{
 	ServiceName: "rpcquery.Query",
 	HandlerType: (*QueryServer)(nil),
@@ -335,6 +450,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{
 			MethodName: "GetName",
 			Handler:    _Query_GetName_Handler,
 		},
+		{
+			MethodName: "GetValidatorSet",
+			Handler:    _Query_GetValidatorSet_Handler,
+		},
 	},
 	Streams: []grpc.StreamDesc{
 		{
@@ -449,6 +568,111 @@ func (m *ListNamesParam) MarshalTo(dAtA []byte) (int, error) {
 	return i, nil
 }
 
+func (m *GetValidatorSetParam) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalTo(dAtA)
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *GetValidatorSetParam) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if m.IncludeHistory {
+		dAtA[i] = 0x8
+		i++
+		if m.IncludeHistory {
+			dAtA[i] = 1
+		} else {
+			dAtA[i] = 0
+		}
+		i++
+	}
+	return i, nil
+}
+
+func (m *ValidatorSet) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalTo(dAtA)
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *ValidatorSet) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if m.Height != 0 {
+		dAtA[i] = 0x8
+		i++
+		i = encodeVarintRpcquery(dAtA, i, uint64(m.Height))
+	}
+	if len(m.Set) > 0 {
+		for _, msg := range m.Set {
+			dAtA[i] = 0x12
+			i++
+			i = encodeVarintRpcquery(dAtA, i, uint64(msg.Size()))
+			n, err := msg.MarshalTo(dAtA[i:])
+			if err != nil {
+				return 0, err
+			}
+			i += n
+		}
+	}
+	if len(m.History) > 0 {
+		for _, msg := range m.History {
+			dAtA[i] = 0x1a
+			i++
+			i = encodeVarintRpcquery(dAtA, i, uint64(msg.Size()))
+			n, err := msg.MarshalTo(dAtA[i:])
+			if err != nil {
+				return 0, err
+			}
+			i += n
+		}
+	}
+	return i, nil
+}
+
+func (m *ValidatorSetDeltas) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalTo(dAtA)
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *ValidatorSetDeltas) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if len(m.Validators) > 0 {
+		for _, msg := range m.Validators {
+			dAtA[i] = 0x12
+			i++
+			i = encodeVarintRpcquery(dAtA, i, uint64(msg.Size()))
+			n, err := msg.MarshalTo(dAtA[i:])
+			if err != nil {
+				return 0, err
+			}
+			i += n
+		}
+	}
+	return i, nil
+}
+
 func encodeVarintRpcquery(dAtA []byte, offset int, v uint64) int {
 	for v >= 1<<7 {
 		dAtA[offset] = uint8(v&0x7f | 0x80)
@@ -496,6 +720,48 @@ func (m *ListNamesParam) Size() (n int) {
 	return n
 }
 
+func (m *GetValidatorSetParam) Size() (n int) {
+	var l int
+	_ = l
+	if m.IncludeHistory {
+		n += 2
+	}
+	return n
+}
+
+func (m *ValidatorSet) Size() (n int) {
+	var l int
+	_ = l
+	if m.Height != 0 {
+		n += 1 + sovRpcquery(uint64(m.Height))
+	}
+	if len(m.Set) > 0 {
+		for _, e := range m.Set {
+			l = e.Size()
+			n += 1 + l + sovRpcquery(uint64(l))
+		}
+	}
+	if len(m.History) > 0 {
+		for _, e := range m.History {
+			l = e.Size()
+			n += 1 + l + sovRpcquery(uint64(l))
+		}
+	}
+	return n
+}
+
+func (m *ValidatorSetDeltas) Size() (n int) {
+	var l int
+	_ = l
+	if len(m.Validators) > 0 {
+		for _, e := range m.Validators {
+			l = e.Size()
+			n += 1 + l + sovRpcquery(uint64(l))
+		}
+	}
+	return n
+}
+
 func sovRpcquery(x uint64) (n int) {
 	for {
 		n++
@@ -826,6 +1092,288 @@ func (m *ListNamesParam) Unmarshal(dAtA []byte) error {
 	}
 	return nil
 }
+func (m *GetValidatorSetParam) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowRpcquery
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: GetValidatorSetParam: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: GetValidatorSetParam: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field IncludeHistory", wireType)
+			}
+			var v int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowRpcquery
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				v |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			m.IncludeHistory = bool(v != 0)
+		default:
+			iNdEx = preIndex
+			skippy, err := skipRpcquery(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthRpcquery
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *ValidatorSet) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowRpcquery
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: ValidatorSet: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: ValidatorSet: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType)
+			}
+			m.Height = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowRpcquery
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Height |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Set", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowRpcquery
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthRpcquery
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Set = append(m.Set, &validator.Validator{})
+			if err := m.Set[len(m.Set)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field History", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowRpcquery
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthRpcquery
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.History = append(m.History, &ValidatorSetDeltas{})
+			if err := m.History[len(m.History)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipRpcquery(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthRpcquery
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *ValidatorSetDeltas) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowRpcquery
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: ValidatorSetDeltas: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: ValidatorSetDeltas: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Validators", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowRpcquery
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthRpcquery
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Validators = append(m.Validators, &validator.Validator{})
+			if err := m.Validators[len(m.Validators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipRpcquery(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthRpcquery
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
 func skipRpcquery(dAtA []byte) (n int, err error) {
 	l := len(dAtA)
 	iNdEx := 0
@@ -935,27 +1483,36 @@ func init() { proto.RegisterFile("rpcquery.proto", fileDescriptorRpcquery) }
 func init() { golang_proto.RegisterFile("rpcquery.proto", fileDescriptorRpcquery) }
 
 var fileDescriptorRpcquery = []byte{
-	// 349 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0xcd, 0x4a, 0xc3, 0x40,
-	0x14, 0x85, 0x1d, 0x50, 0x6b, 0xaf, 0xa1, 0xe2, 0x50, 0xa4, 0x46, 0x48, 0x25, 0x0b, 0x51, 0xd1,
-	0xa4, 0xf8, 0xb3, 0x14, 0x6c, 0x8b, 0x74, 0x23, 0x45, 0xbb, 0x74, 0x97, 0x4c, 0xc7, 0xb4, 0x60,
-	0x32, 0xf1, 0x66, 0x82, 0xe4, 0xed, 0x5c, 0x76, 0xe9, 0xda, 0x45, 0x91, 0xf6, 0x11, 0x7c, 0x01,
-	0xc9, 0x24, 0xe9, 0x8f, 0x4a, 0x77, 0xf7, 0x84, 0x7b, 0xce, 0x99, 0x6f, 0x26, 0x50, 0xc1, 0x90,
-	0xbd, 0xc6, 0x1c, 0x13, 0x2b, 0x44, 0x21, 0x05, 0xdd, 0x2a, 0xb4, 0x7e, 0xee, 0x0d, 0xe5, 0x20,
-	0x76, 0x2d, 0x26, 0x7c, 0xdb, 0x13, 0x9e, 0xb0, 0xd5, 0x82, 0x1b, 0x3f, 0x2b, 0xa5, 0x84, 0x9a,
-	0x32, 0xa3, 0xbe, 0x1d, 0x38, 0x3e, 0x8f, 0x72, 0x51, 0x76, 0x98, 0x9f, 0x8d, 0xa6, 0x03, 0x3b,
-	0x1d, 0x2e, 0x9b, 0x8c, 0x89, 0x38, 0x90, 0x0f, 0x0e, 0x3a, 0x3e, 0xed, 0x42, 0xa9, 0xd9, 0xef,
-	0x23, 0x8f, 0xa2, 0x1a, 0x39, 0x24, 0xc7, 0x5a, 0xeb, 0x6a, 0x34, 0xae, 0xaf, 0x7d, 0x8e, 0xeb,
-	0x67, 0x0b, 0x95, 0x83, 0x24, 0xe4, 0xf8, 0xc2, 0xfb, 0x1e, 0x47, 0xdb, 0x8d, 0x11, 0xc5, 0x9b,
-	0xcd, 0x30, 0x09, 0xa5, 0xb0, 0x72, 0x6f, 0xaf, 0x08, 0x31, 0x4f, 0x60, 0xf7, 0x7e, 0x18, 0x15,
-	0x1d, 0x51, 0x56, 0x52, 0x85, 0x8d, 0xc7, 0x94, 0x43, 0x55, 0x94, 0x7b, 0x99, 0x30, 0x4d, 0xd0,
-	0x3a, 0x5c, 0x76, 0x1d, 0x9f, 0x67, 0x5b, 0x14, 0xd6, 0x53, 0x91, 0x2f, 0xa9, 0xd9, 0x3c, 0x82,
-	0x4a, 0x1a, 0x97, 0xce, 0xab, 0xb2, 0x2e, 0xbe, 0x49, 0xfe, 0x99, 0xde, 0x00, 0xcc, 0x19, 0xe9,
-	0xbe, 0x35, 0xbb, 0xd3, 0x5f, 0xe4, 0x7a, 0xd5, 0x4a, 0x2f, 0xa6, 0x2d, 0x02, 0x86, 0x5c, 0xf2,
-	0xc2, 0xd0, 0x06, 0x6d, 0xf1, 0xfc, 0xf4, 0x60, 0x1e, 0xf0, 0x87, 0xeb, 0xff, 0x88, 0x06, 0xa1,
-	0x36, 0x94, 0x72, 0x32, 0xba, 0xb7, 0x74, 0x80, 0x19, 0xac, 0xae, 0x59, 0xd9, 0x1b, 0xdd, 0x05,
-	0x12, 0x13, 0x7a, 0x0d, 0xe5, 0x19, 0x26, 0xad, 0x2d, 0x57, 0xce, 0xd9, 0x97, 0x4d, 0x0d, 0xd2,
-	0xba, 0x1d, 0x4d, 0x0c, 0xf2, 0x31, 0x31, 0xc8, 0xd7, 0xc4, 0x20, 0xef, 0x53, 0x83, 0x8c, 0xa6,
-	0x06, 0x79, 0x3a, 0x5d, 0xfd, 0x72, 0x18, 0x32, 0xbb, 0x28, 0x70, 0x37, 0xd5, 0x8f, 0x71, 0xf9,
-	0x13, 0x00, 0x00, 0xff, 0xff, 0xfa, 0xef, 0x21, 0x21, 0x7b, 0x02, 0x00, 0x00,
+	// 487 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x53, 0x4f, 0x6f, 0xd3, 0x30,
+	0x1c, 0xc5, 0xeb, 0x58, 0xd7, 0xdf, 0xaa, 0x4e, 0x58, 0x55, 0x55, 0x02, 0xca, 0xa6, 0x1c, 0xaa,
+	0x81, 0x20, 0x99, 0xc6, 0xe0, 0x06, 0x62, 0x1b, 0xa8, 0x0c, 0xa1, 0x09, 0x32, 0x89, 0x03, 0x37,
+	0xd7, 0x31, 0x69, 0xa4, 0x26, 0x0e, 0x8e, 0x03, 0xea, 0x17, 0xe0, 0x63, 0x21, 0x8e, 0x3d, 0x72,
+	0xe6, 0x30, 0xa1, 0xee, 0x8b, 0xa0, 0x38, 0xce, 0xbf, 0x75, 0xea, 0xcd, 0xcf, 0x79, 0xef, 0xf7,
+	0xec, 0xbc, 0x67, 0xe8, 0x89, 0x98, 0x7e, 0x4b, 0x99, 0x98, 0xdb, 0xb1, 0xe0, 0x92, 0xe3, 0xed,
+	0x02, 0x1b, 0x4f, 0xfd, 0x40, 0x4e, 0xd3, 0x89, 0x4d, 0x79, 0xe8, 0xf8, 0xdc, 0xe7, 0x8e, 0x22,
+	0x4c, 0xd2, 0xaf, 0x0a, 0x29, 0xa0, 0x56, 0xb9, 0xd0, 0xd8, 0x89, 0x48, 0xc8, 0x12, 0x0d, 0x3a,
+	0x84, 0x86, 0x7a, 0xb9, 0xfb, 0x9d, 0xcc, 0x02, 0x8f, 0x48, 0x2e, 0xf2, 0x0d, 0x8b, 0xc0, 0xee,
+	0x98, 0xc9, 0x13, 0x4a, 0x79, 0x1a, 0xc9, 0x8f, 0x44, 0x90, 0x10, 0x5f, 0x40, 0xfb, 0xc4, 0xf3,
+	0x04, 0x4b, 0x92, 0x21, 0xda, 0x47, 0x07, 0xdd, 0xd3, 0xe3, 0xc5, 0xd5, 0xde, 0x9d, 0xbf, 0x57,
+	0x7b, 0x4f, 0x6a, 0x67, 0x98, 0xce, 0x63, 0x26, 0x66, 0xcc, 0xf3, 0x99, 0x70, 0x26, 0xa9, 0x10,
+	0xfc, 0x87, 0x43, 0xc5, 0x3c, 0x96, 0xdc, 0xd6, 0x5a, 0xb7, 0x18, 0x62, 0x3d, 0x82, 0x7b, 0x1f,
+	0x82, 0xa4, 0xf0, 0x48, 0x72, 0x93, 0x3e, 0xdc, 0xfd, 0x94, 0x5d, 0x4c, 0x59, 0x74, 0xdc, 0x1c,
+	0x58, 0x16, 0x74, 0xc7, 0x4c, 0x5e, 0x90, 0x90, 0xe5, 0x2c, 0x0c, 0x9b, 0x19, 0xd0, 0x24, 0xb5,
+	0xb6, 0x46, 0xd0, 0xcb, 0xc6, 0x65, 0xeb, 0xb5, 0xb3, 0x5e, 0x41, 0x7f, 0xcc, 0xe4, 0xe7, 0xe2,
+	0xbe, 0x97, 0x4c, 0x5f, 0x6f, 0x04, 0xbd, 0xf3, 0x88, 0xce, 0x52, 0x8f, 0xbd, 0x0b, 0x12, 0xc9,
+	0xb5, 0x6c, 0xdb, 0xbd, 0xb1, 0x6b, 0xfd, 0x44, 0xd0, 0xad, 0xab, 0xf1, 0x00, 0xb6, 0xa6, 0x2c,
+	0xf0, 0xa7, 0x52, 0x09, 0x36, 0x5d, 0x8d, 0xf0, 0x08, 0x5a, 0x97, 0x4c, 0x0e, 0x37, 0xf6, 0x5b,
+	0x07, 0x3b, 0x47, 0x7d, 0xbb, 0xfa, 0xc3, 0xa5, 0xda, 0xcd, 0x08, 0xf8, 0x05, 0xb4, 0x0b, 0xc7,
+	0x96, 0xe2, 0x3e, 0xb4, 0xcb, 0xb8, 0xeb, 0x46, 0x6f, 0xd8, 0x4c, 0x92, 0xc4, 0x2d, 0xc8, 0xd6,
+	0x7b, 0xc0, 0xab, 0x9f, 0xf1, 0x31, 0x40, 0xb9, 0x9b, 0xac, 0x35, 0xaf, 0xf1, 0x8e, 0x7e, 0x6d,
+	0xe8, 0x7f, 0x85, 0x5f, 0x02, 0x54, 0xc1, 0xe3, 0xfb, 0xd5, 0x51, 0x6e, 0xd4, 0xc1, 0xe8, 0xdb,
+	0x59, 0x7d, 0xce, 0x78, 0x44, 0x05, 0x93, 0xac, 0x10, 0x9c, 0x41, 0xb7, 0x1e, 0x2a, 0x7e, 0x50,
+	0x0d, 0x58, 0x09, 0xfb, 0xf6, 0x11, 0x87, 0x08, 0x3b, 0xd0, 0xd6, 0x71, 0xe3, 0x41, 0xe3, 0x00,
+	0x65, 0x03, 0x8c, 0xae, 0x9d, 0x37, 0xf9, 0x6d, 0x24, 0xc5, 0x1c, 0x3f, 0x87, 0x4e, 0x99, 0x3d,
+	0x1e, 0x36, 0x2d, 0xab, 0x42, 0x34, 0x45, 0x87, 0x08, 0x9f, 0xab, 0x92, 0x37, 0xc2, 0x34, 0x1b,
+	0x7e, 0x2b, 0x2d, 0x31, 0x06, 0xb7, 0x67, 0x73, 0xfa, 0x7a, 0xb1, 0x34, 0xd1, 0x9f, 0xa5, 0x89,
+	0xfe, 0x2d, 0x4d, 0xf4, 0xfb, 0xda, 0x44, 0x8b, 0x6b, 0x13, 0x7d, 0x79, 0xbc, 0xfe, 0x65, 0x88,
+	0x98, 0x3a, 0xc5, 0xb8, 0xc9, 0x96, 0x7a, 0x78, 0xcf, 0xfe, 0x07, 0x00, 0x00, 0xff, 0xff, 0xfd,
+	0xa4, 0xb6, 0xf9, 0xec, 0x03, 0x00, 0x00,
 }
diff --git a/rpc/rpctransact/rpctransact.pb.go b/rpc/rpctransact/rpctransact.pb.go
index 903e977b..98861547 100644
--- a/rpc/rpctransact/rpctransact.pb.go
+++ b/rpc/rpctransact/rpctransact.pb.go
@@ -9,7 +9,6 @@
 
 	It has these top-level messages:
 		CallCodeParam
-		PayloadParam
 		TxEnvelope
 		TxEnvelopeParam
 */
@@ -73,42 +72,6 @@ func (*CallCodeParam) XXX_MessageName() string {
 	return "rpctransact.CallCodeParam"
 }
 
-type PayloadParam struct {
-	CallTx *payload.CallTx `protobuf:"bytes,1,opt,name=CallTx" json:"CallTx,omitempty"`
-	SendTx *payload.SendTx `protobuf:"bytes,2,opt,name=SendTx" json:"SendTx,omitempty"`
-	NameTx *payload.NameTx `protobuf:"bytes,3,opt,name=NameTx" json:"NameTx,omitempty"`
-}
-
-func (m *PayloadParam) Reset()                    { *m = PayloadParam{} }
-func (m *PayloadParam) String() string            { return proto.CompactTextString(m) }
-func (*PayloadParam) ProtoMessage()               {}
-func (*PayloadParam) Descriptor() ([]byte, []int) { return fileDescriptorRpctransact, []int{1} }
-
-func (m *PayloadParam) GetCallTx() *payload.CallTx {
-	if m != nil {
-		return m.CallTx
-	}
-	return nil
-}
-
-func (m *PayloadParam) GetSendTx() *payload.SendTx {
-	if m != nil {
-		return m.SendTx
-	}
-	return nil
-}
-
-func (m *PayloadParam) GetNameTx() *payload.NameTx {
-	if m != nil {
-		return m.NameTx
-	}
-	return nil
-}
-
-func (*PayloadParam) XXX_MessageName() string {
-	return "rpctransact.PayloadParam"
-}
-
 type TxEnvelope struct {
 	Envelope *github_com_hyperledger_burrow_txs.Envelope `protobuf:"bytes,1,opt,name=Envelope,customtype=github.com/hyperledger/burrow/txs.Envelope" json:"Envelope,omitempty"`
 }
@@ -116,7 +79,7 @@ type TxEnvelope struct {
 func (m *TxEnvelope) Reset()                    { *m = TxEnvelope{} }
 func (m *TxEnvelope) String() string            { return proto.CompactTextString(m) }
 func (*TxEnvelope) ProtoMessage()               {}
-func (*TxEnvelope) Descriptor() ([]byte, []int) { return fileDescriptorRpctransact, []int{2} }
+func (*TxEnvelope) Descriptor() ([]byte, []int) { return fileDescriptorRpctransact, []int{1} }
 
 func (*TxEnvelope) XXX_MessageName() string {
 	return "rpctransact.TxEnvelope"
@@ -126,15 +89,15 @@ type TxEnvelopeParam struct {
 	// An existing Envelope - either signed or unsigned - if the latter will be signed server-side
 	Envelope *github_com_hyperledger_burrow_txs.Envelope `protobuf:"bytes,1,opt,name=Envelope,customtype=github.com/hyperledger/burrow/txs.Envelope" json:"Envelope,omitempty"`
 	// If no Envelope provided then one will be generated from the provided payload and signed server-side
-	Payload *PayloadParam `protobuf:"bytes,2,opt,name=Payload" json:"Payload,omitempty"`
+	Payload *payload.Any `protobuf:"bytes,2,opt,name=Payload" json:"Payload,omitempty"`
 }
 
 func (m *TxEnvelopeParam) Reset()                    { *m = TxEnvelopeParam{} }
 func (m *TxEnvelopeParam) String() string            { return proto.CompactTextString(m) }
 func (*TxEnvelopeParam) ProtoMessage()               {}
-func (*TxEnvelopeParam) Descriptor() ([]byte, []int) { return fileDescriptorRpctransact, []int{3} }
+func (*TxEnvelopeParam) Descriptor() ([]byte, []int) { return fileDescriptorRpctransact, []int{2} }
 
-func (m *TxEnvelopeParam) GetPayload() *PayloadParam {
+func (m *TxEnvelopeParam) GetPayload() *payload.Any {
 	if m != nil {
 		return m.Payload
 	}
@@ -147,8 +110,6 @@ func (*TxEnvelopeParam) XXX_MessageName() string {
 func init() {
 	proto.RegisterType((*CallCodeParam)(nil), "rpctransact.CallCodeParam")
 	golang_proto.RegisterType((*CallCodeParam)(nil), "rpctransact.CallCodeParam")
-	proto.RegisterType((*PayloadParam)(nil), "rpctransact.PayloadParam")
-	golang_proto.RegisterType((*PayloadParam)(nil), "rpctransact.PayloadParam")
 	proto.RegisterType((*TxEnvelope)(nil), "rpctransact.TxEnvelope")
 	golang_proto.RegisterType((*TxEnvelope)(nil), "rpctransact.TxEnvelope")
 	proto.RegisterType((*TxEnvelopeParam)(nil), "rpctransact.TxEnvelopeParam")
@@ -174,7 +135,7 @@ type TransactClient interface {
 	// Sign transaction server-side
 	SignTx(ctx context.Context, in *TxEnvelopeParam, opts ...grpc.CallOption) (*TxEnvelope, error)
 	// Formulate a transaction from a Payload and retrun the envelop with the Tx bytes ready to sign
-	FormulateTx(ctx context.Context, in *PayloadParam, opts ...grpc.CallOption) (*TxEnvelope, error)
+	FormulateTx(ctx context.Context, in *payload.Any, opts ...grpc.CallOption) (*TxEnvelope, error)
 	// Formulate and sign a CallTx transaction signed server-side and wait for it to be included in a block, retrieving response
 	CallTxSync(ctx context.Context, in *payload.CallTx, opts ...grpc.CallOption) (*exec.TxExecution, error)
 	// Formulate and sign a CallTx transaction signed server-side
@@ -229,7 +190,7 @@ func (c *transactClient) SignTx(ctx context.Context, in *TxEnvelopeParam, opts .
 	return out, nil
 }
 
-func (c *transactClient) FormulateTx(ctx context.Context, in *PayloadParam, opts ...grpc.CallOption) (*TxEnvelope, error) {
+func (c *transactClient) FormulateTx(ctx context.Context, in *payload.Any, opts ...grpc.CallOption) (*TxEnvelope, error) {
 	out := new(TxEnvelope)
 	err := grpc.Invoke(ctx, "/rpctransact.Transact/FormulateTx", in, out, c.cc, opts...)
 	if err != nil {
@@ -321,7 +282,7 @@ type TransactServer interface {
 	// Sign transaction server-side
 	SignTx(context.Context, *TxEnvelopeParam) (*TxEnvelope, error)
 	// Formulate a transaction from a Payload and retrun the envelop with the Tx bytes ready to sign
-	FormulateTx(context.Context, *PayloadParam) (*TxEnvelope, error)
+	FormulateTx(context.Context, *payload.Any) (*TxEnvelope, error)
 	// Formulate and sign a CallTx transaction signed server-side and wait for it to be included in a block, retrieving response
 	CallTxSync(context.Context, *payload.CallTx) (*exec.TxExecution, error)
 	// Formulate and sign a CallTx transaction signed server-side
@@ -400,7 +361,7 @@ func _Transact_SignTx_Handler(srv interface{}, ctx context.Context, dec func(int
 }
 
 func _Transact_FormulateTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(PayloadParam)
+	in := new(payload.Any)
 	if err := dec(in); err != nil {
 		return nil, err
 	}
@@ -412,7 +373,7 @@ func _Transact_FormulateTx_Handler(srv interface{}, ctx context.Context, dec fun
 		FullMethod: "/rpctransact.Transact/FormulateTx",
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(TransactServer).FormulateTx(ctx, req.(*PayloadParam))
+		return srv.(TransactServer).FormulateTx(ctx, req.(*payload.Any))
 	}
 	return interceptor(ctx, in, info, handler)
 }
@@ -656,54 +617,6 @@ func (m *CallCodeParam) MarshalTo(dAtA []byte) (int, error) {
 	return i, nil
 }
 
-func (m *PayloadParam) Marshal() (dAtA []byte, err error) {
-	size := m.Size()
-	dAtA = make([]byte, size)
-	n, err := m.MarshalTo(dAtA)
-	if err != nil {
-		return nil, err
-	}
-	return dAtA[:n], nil
-}
-
-func (m *PayloadParam) MarshalTo(dAtA []byte) (int, error) {
-	var i int
-	_ = i
-	var l int
-	_ = l
-	if m.CallTx != nil {
-		dAtA[i] = 0xa
-		i++
-		i = encodeVarintRpctransact(dAtA, i, uint64(m.CallTx.Size()))
-		n2, err := m.CallTx.MarshalTo(dAtA[i:])
-		if err != nil {
-			return 0, err
-		}
-		i += n2
-	}
-	if m.SendTx != nil {
-		dAtA[i] = 0x12
-		i++
-		i = encodeVarintRpctransact(dAtA, i, uint64(m.SendTx.Size()))
-		n3, err := m.SendTx.MarshalTo(dAtA[i:])
-		if err != nil {
-			return 0, err
-		}
-		i += n3
-	}
-	if m.NameTx != nil {
-		dAtA[i] = 0x1a
-		i++
-		i = encodeVarintRpctransact(dAtA, i, uint64(m.NameTx.Size()))
-		n4, err := m.NameTx.MarshalTo(dAtA[i:])
-		if err != nil {
-			return 0, err
-		}
-		i += n4
-	}
-	return i, nil
-}
-
 func (m *TxEnvelope) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	dAtA = make([]byte, size)
@@ -723,11 +636,11 @@ func (m *TxEnvelope) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0xa
 		i++
 		i = encodeVarintRpctransact(dAtA, i, uint64(m.Envelope.Size()))
-		n5, err := m.Envelope.MarshalTo(dAtA[i:])
+		n2, err := m.Envelope.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n5
+		i += n2
 	}
 	return i, nil
 }
@@ -751,21 +664,21 @@ func (m *TxEnvelopeParam) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0xa
 		i++
 		i = encodeVarintRpctransact(dAtA, i, uint64(m.Envelope.Size()))
-		n6, err := m.Envelope.MarshalTo(dAtA[i:])
+		n3, err := m.Envelope.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n6
+		i += n3
 	}
 	if m.Payload != nil {
 		dAtA[i] = 0x12
 		i++
 		i = encodeVarintRpctransact(dAtA, i, uint64(m.Payload.Size()))
-		n7, err := m.Payload.MarshalTo(dAtA[i:])
+		n4, err := m.Payload.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n7
+		i += n4
 	}
 	return i, nil
 }
@@ -795,24 +708,6 @@ func (m *CallCodeParam) Size() (n int) {
 	return n
 }
 
-func (m *PayloadParam) Size() (n int) {
-	var l int
-	_ = l
-	if m.CallTx != nil {
-		l = m.CallTx.Size()
-		n += 1 + l + sovRpctransact(uint64(l))
-	}
-	if m.SendTx != nil {
-		l = m.SendTx.Size()
-		n += 1 + l + sovRpctransact(uint64(l))
-	}
-	if m.NameTx != nil {
-		l = m.NameTx.Size()
-		n += 1 + l + sovRpctransact(uint64(l))
-	}
-	return n
-}
-
 func (m *TxEnvelope) Size() (n int) {
 	var l int
 	_ = l
@@ -992,155 +887,6 @@ func (m *CallCodeParam) Unmarshal(dAtA []byte) error {
 	}
 	return nil
 }
-func (m *PayloadParam) Unmarshal(dAtA []byte) error {
-	l := len(dAtA)
-	iNdEx := 0
-	for iNdEx < l {
-		preIndex := iNdEx
-		var wire uint64
-		for shift := uint(0); ; shift += 7 {
-			if shift >= 64 {
-				return ErrIntOverflowRpctransact
-			}
-			if iNdEx >= l {
-				return io.ErrUnexpectedEOF
-			}
-			b := dAtA[iNdEx]
-			iNdEx++
-			wire |= (uint64(b) & 0x7F) << shift
-			if b < 0x80 {
-				break
-			}
-		}
-		fieldNum := int32(wire >> 3)
-		wireType := int(wire & 0x7)
-		if wireType == 4 {
-			return fmt.Errorf("proto: PayloadParam: wiretype end group for non-group")
-		}
-		if fieldNum <= 0 {
-			return fmt.Errorf("proto: PayloadParam: illegal tag %d (wire type %d)", fieldNum, wire)
-		}
-		switch fieldNum {
-		case 1:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field CallTx", wireType)
-			}
-			var msglen int
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowRpctransact
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				msglen |= (int(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			if msglen < 0 {
-				return ErrInvalidLengthRpctransact
-			}
-			postIndex := iNdEx + msglen
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			if m.CallTx == nil {
-				m.CallTx = &payload.CallTx{}
-			}
-			if err := m.CallTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
-				return err
-			}
-			iNdEx = postIndex
-		case 2:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field SendTx", wireType)
-			}
-			var msglen int
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowRpctransact
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				msglen |= (int(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			if msglen < 0 {
-				return ErrInvalidLengthRpctransact
-			}
-			postIndex := iNdEx + msglen
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			if m.SendTx == nil {
-				m.SendTx = &payload.SendTx{}
-			}
-			if err := m.SendTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
-				return err
-			}
-			iNdEx = postIndex
-		case 3:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field NameTx", wireType)
-			}
-			var msglen int
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowRpctransact
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				msglen |= (int(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			if msglen < 0 {
-				return ErrInvalidLengthRpctransact
-			}
-			postIndex := iNdEx + msglen
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			if m.NameTx == nil {
-				m.NameTx = &payload.NameTx{}
-			}
-			if err := m.NameTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
-				return err
-			}
-			iNdEx = postIndex
-		default:
-			iNdEx = preIndex
-			skippy, err := skipRpctransact(dAtA[iNdEx:])
-			if err != nil {
-				return err
-			}
-			if skippy < 0 {
-				return ErrInvalidLengthRpctransact
-			}
-			if (iNdEx + skippy) > l {
-				return io.ErrUnexpectedEOF
-			}
-			iNdEx += skippy
-		}
-	}
-
-	if iNdEx > l {
-		return io.ErrUnexpectedEOF
-	}
-	return nil
-}
 func (m *TxEnvelope) Unmarshal(dAtA []byte) error {
 	l := len(dAtA)
 	iNdEx := 0
@@ -1313,7 +1059,7 @@ func (m *TxEnvelopeParam) Unmarshal(dAtA []byte) error {
 				return io.ErrUnexpectedEOF
 			}
 			if m.Payload == nil {
-				m.Payload = &PayloadParam{}
+				m.Payload = &payload.Any{}
 			}
 			if err := m.Payload.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 				return err
@@ -1449,40 +1195,37 @@ func init() { proto.RegisterFile("rpctransact.proto", fileDescriptorRpctransact)
 func init() { golang_proto.RegisterFile("rpctransact.proto", fileDescriptorRpctransact) }
 
 var fileDescriptorRpctransact = []byte{
-	// 552 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x54, 0xcd, 0x6e, 0xd3, 0x40,
-	0x10, 0xc6, 0xfc, 0x84, 0x76, 0x92, 0x28, 0x74, 0x2f, 0x84, 0x08, 0x25, 0x28, 0x17, 0x10, 0x6a,
-	0xed, 0xa8, 0xe5, 0x88, 0x40, 0x49, 0x68, 0x8f, 0xa8, 0x72, 0x2c, 0x24, 0xb8, 0x6d, 0xec, 0xc5,
-	0x8d, 0x64, 0x7b, 0xad, 0xf5, 0x06, 0x36, 0x8f, 0xc0, 0x89, 0x67, 0xe8, 0x9b, 0x70, 0xcc, 0x91,
-	0x73, 0x0f, 0x11, 0x4a, 0x5f, 0x04, 0xed, 0x4f, 0x60, 0x6d, 0x9a, 0x96, 0x4b, 0x6f, 0xe3, 0x6f,
-	0x66, 0xbe, 0x99, 0xef, 0xd3, 0x8e, 0x61, 0x8f, 0xe5, 0x21, 0x67, 0x38, 0x2b, 0x70, 0xc8, 0xdd,
-	0x9c, 0x51, 0x4e, 0x51, 0xdd, 0x82, 0x3a, 0x07, 0xf1, 0x8c, 0x9f, 0xcd, 0xa7, 0x6e, 0x48, 0x53,
-	0x2f, 0xa6, 0x31, 0xf5, 0x54, 0xcd, 0x74, 0xfe, 0x59, 0x7d, 0xa9, 0x0f, 0x15, 0xe9, 0xde, 0x0e,
-	0x10, 0x41, 0x42, 0x13, 0x37, 0x73, 0xbc, 0x48, 0x28, 0x8e, 0xcc, 0xe7, 0x2e, 0x17, 0x85, 0x0e,
-	0xfb, 0xdf, 0x1d, 0x68, 0x8e, 0x71, 0x92, 0x8c, 0x69, 0x44, 0x4e, 0x31, 0xc3, 0x29, 0xfa, 0x00,
-	0xf5, 0x13, 0x46, 0xd3, 0x61, 0x14, 0x31, 0x52, 0x14, 0x6d, 0xe7, 0x99, 0xf3, 0xa2, 0x31, 0x7a,
-	0xb5, 0x5c, 0xf5, 0xee, 0x5c, 0xac, 0x7a, 0xfb, 0xd6, 0x0e, 0x67, 0x8b, 0x9c, 0xb0, 0x84, 0x44,
-	0x31, 0x61, 0xde, 0x74, 0xce, 0x18, 0xfd, 0xea, 0x85, 0x6c, 0x91, 0x73, 0xea, 0x9a, 0x5e, 0xdf,
-	0x26, 0x42, 0x08, 0xee, 0xcb, 0x21, 0xed, 0xbb, 0x92, 0xd0, 0x57, 0xb1, 0xc4, 0xde, 0x61, 0x8e,
-	0xdb, 0xf7, 0x34, 0x26, 0xe3, 0xfe, 0x37, 0x07, 0x1a, 0xa7, 0x7a, 0x5d, 0xbd, 0xd0, 0x73, 0xa8,
-	0xc9, 0x0d, 0x03, 0xa1, 0x76, 0xa9, 0x1f, 0xb6, 0xdc, 0x8d, 0x1a, 0x0d, 0xfb, 0x26, 0x2d, 0x0b,
-	0x27, 0x24, 0x8b, 0x02, 0xa1, 0x66, 0xd8, 0x85, 0x1a, 0xf6, 0x4d, 0x5a, 0x16, 0xbe, 0xc7, 0x29,
-	0x09, 0x84, 0x1a, 0x6c, 0x17, 0x6a, 0xd8, 0x37, 0xe9, 0x7e, 0x0c, 0x10, 0x88, 0xe3, 0xec, 0x0b,
-	0x49, 0x68, 0x4e, 0xd0, 0x47, 0xd8, 0xd9, 0xc4, 0x66, 0x95, 0xa6, 0x2b, 0x9d, 0xdc, 0x80, 0x23,
-	0xf7, 0x62, 0xd5, 0x7b, 0x79, 0xbd, 0x43, 0x76, 0xbd, 0xff, 0x87, 0xae, 0x7f, 0xee, 0x40, 0xeb,
-	0xef, 0x24, 0xad, 0xfb, 0xf6, 0xc6, 0xa1, 0x23, 0x78, 0x68, 0x2c, 0x36, 0x56, 0x3d, 0x71, 0xed,
-	0xc7, 0x67, 0xdb, 0xef, 0x6f, 0x2a, 0x0f, 0xcf, 0x1f, 0xc0, 0x4e, 0x60, 0x4a, 0xd0, 0x08, 0x5a,
-	0x23, 0x46, 0x71, 0x14, 0xe2, 0x82, 0x07, 0x62, 0xb2, 0xc8, 0x42, 0xf4, 0xb4, 0xc4, 0x51, 0x51,
-	0xd3, 0xd9, 0x73, 0xd5, 0x7b, 0x0c, 0xc4, 0xb1, 0x20, 0xe1, 0x9c, 0xcf, 0x68, 0x86, 0xde, 0xc0,
-	0x23, 0x8b, 0x63, 0x58, 0xdc, 0x4c, 0xd2, 0x50, 0x06, 0xf8, 0x24, 0x24, 0xb3, 0x9c, 0xa3, 0xb7,
-	0x50, 0x9b, 0xcc, 0xe2, 0x2c, 0x10, 0x37, 0x74, 0x3d, 0xde, 0x92, 0x45, 0x43, 0xa8, 0x9f, 0x50,
-	0x96, 0xce, 0x13, 0xcc, 0x49, 0x20, 0xd0, 0x76, 0x13, 0xb6, 0x53, 0x0c, 0x00, 0xf4, 0xeb, 0x53,
-	0x16, 0x54, 0x9f, 0xe6, 0x55, 0xaa, 0xf7, 0xa1, 0xae, 0x93, 0x5a, 0xf0, 0x3f, 0x2d, 0x65, 0x8d,
-	0x1e, 0xec, 0x1a, 0xfe, 0x59, 0xfa, 0x5f, 0xf4, 0xaf, 0x35, 0xbd, 0x3c, 0x2f, 0xd9, 0xd2, 0x29,
-	0x2d, 0x5e, 0xba, 0xf4, 0xab, 0xba, 0x07, 0x00, 0xfa, 0x46, 0x2a, 0x72, 0x34, 0xb8, 0x45, 0x8e,
-	0x4e, 0x56, 0xe5, 0x98, 0x96, 0xb2, 0x9c, 0x01, 0x80, 0x3e, 0xad, 0x0a, 0xbf, 0x06, 0xb7, 0xf0,
-	0xeb, 0x64, 0x95, 0xdf, 0xb4, 0x94, 0xf8, 0x47, 0xe3, 0xe5, 0xba, 0xeb, 0xfc, 0x5c, 0x77, 0x9d,
-	0x5f, 0xeb, 0xae, 0xf3, 0xe3, 0xb2, 0xeb, 0x2c, 0x2f, 0xbb, 0xce, 0xa7, 0x83, 0xeb, 0x8f, 0x84,
-	0xe5, 0xa1, 0x67, 0xb9, 0x34, 0xad, 0xa9, 0x5f, 0xe3, 0xd1, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff,
-	0x0f, 0x15, 0x24, 0xfe, 0x91, 0x05, 0x00, 0x00,
+	// 506 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x54, 0xcf, 0x6f, 0xd3, 0x30,
+	0x18, 0x25, 0xfc, 0x18, 0xdb, 0x97, 0x56, 0x65, 0xbe, 0x50, 0x55, 0x28, 0x45, 0x3d, 0x20, 0x84,
+	0xb6, 0xa4, 0x2a, 0x3b, 0x22, 0x50, 0x53, 0xb6, 0x23, 0x9a, 0xd2, 0x08, 0x09, 0x6e, 0xae, 0x63,
+	0xb2, 0x48, 0x49, 0x1c, 0x39, 0x0e, 0x24, 0x7f, 0x05, 0x97, 0xfd, 0x41, 0x1c, 0x7b, 0xe4, 0xbc,
+	0x43, 0x85, 0xba, 0x7f, 0x04, 0xc5, 0x4e, 0x47, 0xd2, 0xae, 0x2b, 0x97, 0xdd, 0x9e, 0xdf, 0x97,
+	0xf7, 0xfc, 0x3d, 0x7f, 0x76, 0xe0, 0x90, 0x27, 0x44, 0x70, 0x1c, 0xa7, 0x98, 0x08, 0x33, 0xe1,
+	0x4c, 0x30, 0xa4, 0xd7, 0xa8, 0xde, 0xb1, 0x1f, 0x88, 0x8b, 0x6c, 0x66, 0x12, 0x16, 0x59, 0x3e,
+	0xf3, 0x99, 0x25, 0xbf, 0x99, 0x65, 0xdf, 0xe4, 0x4a, 0x2e, 0x24, 0x52, 0xda, 0x1e, 0xd0, 0x9c,
+	0x92, 0x0a, 0xb7, 0x13, 0x5c, 0x84, 0x0c, 0x7b, 0xd5, 0xf2, 0x40, 0xe4, 0xa9, 0x82, 0x83, 0x9f,
+	0x1a, 0xb4, 0x27, 0x38, 0x0c, 0x27, 0xcc, 0xa3, 0xe7, 0x98, 0xe3, 0x08, 0x7d, 0x06, 0xfd, 0x8c,
+	0xb3, 0x68, 0xec, 0x79, 0x9c, 0xa6, 0x69, 0x57, 0x7b, 0xa9, 0xbd, 0x6e, 0xd9, 0x27, 0xf3, 0x45,
+	0xff, 0xc1, 0xd5, 0xa2, 0x7f, 0x54, 0xeb, 0xe1, 0xa2, 0x48, 0x28, 0x0f, 0xa9, 0xe7, 0x53, 0x6e,
+	0xcd, 0x32, 0xce, 0xd9, 0x0f, 0x8b, 0xf0, 0x22, 0x11, 0xcc, 0xac, 0xb4, 0x4e, 0xdd, 0x08, 0x21,
+	0x78, 0x5c, 0x6e, 0xd2, 0x7d, 0x58, 0x1a, 0x3a, 0x12, 0x97, 0xdc, 0x47, 0x2c, 0x70, 0xf7, 0x91,
+	0xe2, 0x4a, 0x3c, 0xf0, 0x01, 0xdc, 0xfc, 0x34, 0xfe, 0x4e, 0x43, 0x96, 0x50, 0xf4, 0x05, 0xf6,
+	0x57, 0x58, 0xb6, 0xa2, 0x8f, 0xda, 0x66, 0xd9, 0xfd, 0x8a, 0xb4, 0xcd, 0xab, 0x45, 0xff, 0xcd,
+	0xdd, 0x5d, 0xd5, 0xbf, 0x77, 0x6e, 0xec, 0x06, 0x97, 0x1a, 0x74, 0xfe, 0xed, 0xa4, 0xc2, 0xdf,
+	0xdf, 0x76, 0xe8, 0x15, 0x3c, 0x3d, 0x57, 0x53, 0x90, 0x47, 0xa0, 0x8f, 0x5a, 0xe6, 0x6a, 0x2a,
+	0xe3, 0xb8, 0x70, 0x56, 0xc5, 0xd1, 0xe5, 0x13, 0xd8, 0x77, 0xab, 0x99, 0x23, 0x1b, 0x3a, 0x36,
+	0x67, 0xd8, 0x23, 0x38, 0x15, 0x6e, 0x3e, 0x2d, 0x62, 0x82, 0x5e, 0x98, 0xf5, 0x7b, 0xb2, 0x16,
+	0xa0, 0x77, 0x68, 0xca, 0xb1, 0xbb, 0xf9, 0x69, 0x4e, 0x49, 0x26, 0x02, 0x16, 0xa3, 0xf7, 0xf0,
+	0xac, 0xe6, 0x31, 0x4e, 0x77, 0x9b, 0xb4, 0x64, 0x66, 0x87, 0x12, 0x1a, 0x24, 0x02, 0x7d, 0x80,
+	0xbd, 0x69, 0xe0, 0xc7, 0x6e, 0xbe, 0x43, 0xf5, 0x7c, 0x4b, 0x15, 0x9d, 0x80, 0x7e, 0xc6, 0x78,
+	0x94, 0x85, 0x58, 0x50, 0x37, 0x47, 0x8d, 0xdc, 0xdb, 0x55, 0x43, 0x80, 0xf2, 0x62, 0x56, 0xa9,
+	0x3b, 0x37, 0x22, 0x45, 0xde, 0x16, 0xf4, 0x08, 0x74, 0x55, 0x54, 0x19, 0x37, 0x24, 0xcd, 0x58,
+	0x16, 0x1c, 0x54, 0xfe, 0x41, 0xf4, 0x5f, 0xf6, 0xef, 0x94, 0x7d, 0x79, 0x71, 0x4b, 0x49, 0xaf,
+	0xd1, 0x78, 0xe3, 0x0d, 0xdd, 0xa6, 0x1e, 0x02, 0x4c, 0x69, 0xec, 0x6d, 0xc4, 0x51, 0xe4, 0x96,
+	0x38, 0xaa, 0xb8, 0x1e, 0xa7, 0x92, 0x34, 0xe3, 0x0c, 0x01, 0x3e, 0xe1, 0x88, 0x6e, 0xf8, 0x2b,
+	0x72, 0x8b, 0xbf, 0x2a, 0xae, 0xfb, 0x57, 0x92, 0x86, 0xbf, 0x3d, 0x99, 0x2f, 0x0d, 0xed, 0xf7,
+	0xd2, 0xd0, 0xfe, 0x2c, 0x0d, 0xed, 0xd7, 0xb5, 0xa1, 0xcd, 0xaf, 0x0d, 0xed, 0xeb, 0xf1, 0xdd,
+	0x4f, 0x81, 0x27, 0xc4, 0xaa, 0x9d, 0xd2, 0x6c, 0x4f, 0xfe, 0x74, 0xde, 0xfe, 0x0d, 0x00, 0x00,
+	0xff, 0xff, 0xd4, 0x01, 0x16, 0xdf, 0xeb, 0x04, 0x00, 0x00,
 }
diff --git a/rpc/rpctransact/transact_server.go b/rpc/rpctransact/transact_server.go
index ab3a8c6e..d2e0a9b4 100644
--- a/rpc/rpctransact/transact_server.go
+++ b/rpc/rpctransact/transact_server.go
@@ -52,8 +52,8 @@ func (ts *transactServer) SignTx(ctx context.Context, param *TxEnvelopeParam) (*
 	}, nil
 }
 
-func (ts *transactServer) FormulateTx(ctx context.Context, param *PayloadParam) (*TxEnvelope, error) {
-	txEnv := param.Envelope(ts.transactor.Tip.ChainID())
+func (ts *transactServer) FormulateTx(ctx context.Context, param *payload.Any) (*TxEnvelope, error) {
+	txEnv := EnvelopeFromAny(ts.transactor.Tip.ChainID(), param)
 	if txEnv == nil {
 		return nil, fmt.Errorf("no payload provided to FormulateTx")
 	}
@@ -63,11 +63,11 @@ func (ts *transactServer) FormulateTx(ctx context.Context, param *PayloadParam)
 }
 
 func (ts *transactServer) CallTxSync(ctx context.Context, param *payload.CallTx) (*exec.TxExecution, error) {
-	return ts.BroadcastTxSync(ctx, txEnvelopeParam(param))
+	return ts.BroadcastTxSync(ctx, &TxEnvelopeParam{Payload: param.Any()})
 }
 
 func (ts *transactServer) CallTxAsync(ctx context.Context, param *payload.CallTx) (*txs.Receipt, error) {
-	return ts.BroadcastTxAsync(ctx, txEnvelopeParam(param))
+	return ts.BroadcastTxAsync(ctx, &TxEnvelopeParam{Payload: param.Any()})
 }
 
 func (ts *transactServer) CallTxSim(ctx context.Context, param *payload.CallTx) (*exec.TxExecution, error) {
@@ -82,19 +82,19 @@ func (ts *transactServer) CallCodeSim(ctx context.Context, param *CallCodeParam)
 }
 
 func (ts *transactServer) SendTxSync(ctx context.Context, param *payload.SendTx) (*exec.TxExecution, error) {
-	return ts.BroadcastTxSync(ctx, txEnvelopeParam(param))
+	return ts.BroadcastTxSync(ctx, &TxEnvelopeParam{Payload: param.Any()})
 }
 
 func (ts *transactServer) SendTxAsync(ctx context.Context, param *payload.SendTx) (*txs.Receipt, error) {
-	return ts.BroadcastTxAsync(ctx, txEnvelopeParam(param))
+	return ts.BroadcastTxAsync(ctx, &TxEnvelopeParam{Payload: param.Any()})
 }
 
 func (ts *transactServer) NameTxSync(ctx context.Context, param *payload.NameTx) (*exec.TxExecution, error) {
-	return ts.BroadcastTxSync(ctx, txEnvelopeParam(param))
+	return ts.BroadcastTxSync(ctx, &TxEnvelopeParam{Payload: param.Any()})
 }
 
 func (ts *transactServer) NameTxAsync(ctx context.Context, param *payload.NameTx) (*txs.Receipt, error) {
-	return ts.BroadcastTxAsync(ctx, txEnvelopeParam(param))
+	return ts.BroadcastTxAsync(ctx, &TxEnvelopeParam{Payload: param.Any()})
 }
 
 func (te *TxEnvelopeParam) GetEnvelope(chainID string) *txs.Envelope {
@@ -105,44 +105,26 @@ func (te *TxEnvelopeParam) GetEnvelope(chainID string) *txs.Envelope {
 		return te.Envelope
 	}
 	if te.Payload != nil {
-		return te.Payload.Envelope(chainID)
+		return EnvelopeFromAny(chainID, te.Payload)
 	}
 	return nil
 }
 
-func (pp *PayloadParam) Envelope(chainID string) *txs.Envelope {
-	if pp.CallTx != nil {
-		return txs.Enclose(chainID, pp.CallTx)
+func EnvelopeFromAny(chainID string, p *payload.Any) *txs.Envelope {
+	if p.CallTx != nil {
+		return txs.Enclose(chainID, p.CallTx)
 	}
-	if pp.SendTx != nil {
-		return txs.Enclose(chainID, pp.SendTx)
+	if p.SendTx != nil {
+		return txs.Enclose(chainID, p.SendTx)
 	}
-	if pp.NameTx != nil {
-		return txs.Enclose(chainID, pp.NameTx)
+	if p.NameTx != nil {
+		return txs.Enclose(chainID, p.NameTx)
 	}
-	return nil
-}
-
-func txEnvelopeParam(pl payload.Payload) *TxEnvelopeParam {
-	switch tx := pl.(type) {
-	case *payload.CallTx:
-		return &TxEnvelopeParam{
-			Payload: &PayloadParam{
-				CallTx: tx,
-			},
-		}
-	case *payload.SendTx:
-		return &TxEnvelopeParam{
-			Payload: &PayloadParam{
-				SendTx: tx,
-			},
-		}
-	case *payload.NameTx:
-		return &TxEnvelopeParam{
-			Payload: &PayloadParam{
-				NameTx: tx,
-			},
-		}
+	if p.PermsTx != nil {
+		return txs.Enclose(chainID, p.PermsTx)
+	}
+	if p.GovTx != nil {
+		return txs.Enclose(chainID, p.GovTx)
 	}
 	return nil
 }
diff --git a/rpc/service.go b/rpc/service.go
index 42ebc1cf..3c266ad2 100644
--- a/rpc/service.go
+++ b/rpc/service.go
@@ -22,11 +22,11 @@ import (
 
 	"github.com/hyperledger/burrow/acm"
 	"github.com/hyperledger/burrow/acm/state"
+	"github.com/hyperledger/burrow/acm/validator"
+	"github.com/hyperledger/burrow/bcm"
 	"github.com/hyperledger/burrow/binary"
-	bcm "github.com/hyperledger/burrow/blockchain"
-	"github.com/hyperledger/burrow/consensus/tendermint/query"
+	"github.com/hyperledger/burrow/consensus/tendermint"
 	"github.com/hyperledger/burrow/crypto"
-	"github.com/hyperledger/burrow/execution"
 	"github.com/hyperledger/burrow/execution/names"
 	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/logging/structure"
@@ -45,31 +45,24 @@ type Service struct {
 	state      state.IterableReader
 	nameReg    names.IterableReader
 	blockchain bcm.BlockchainInfo
-	transactor *execution.Transactor
-	nodeView   *query.NodeView
+	nodeView   *tendermint.NodeView
 	logger     *logging.Logger
 }
 
-func NewService(state state.IterableReader, nameReg names.IterableReader,
-	blockchain bcm.BlockchainInfo, transactor *execution.Transactor, nodeView *query.NodeView,
-	logger *logging.Logger) *Service {
+// Service provides an internal query and information service with serialisable return types on which can accomodate
+// a number of transport front ends
+func NewService(state state.IterableReader, nameReg names.IterableReader, blockchain bcm.BlockchainInfo,
+	nodeView *tendermint.NodeView, logger *logging.Logger) *Service {
 
 	return &Service{
 		state:      state,
 		nameReg:    nameReg,
 		blockchain: blockchain,
-		transactor: transactor,
 		nodeView:   nodeView,
 		logger:     logger.With(structure.ComponentKey, "Service"),
 	}
 }
 
-// Get a Transactor providing methods for delegating signing and the core BroadcastTx function for publishing
-// transactions to the network
-func (s *Service) Transactor() *execution.Transactor {
-	return s.transactor
-}
-
 func (s *Service) State() state.Reader {
 	return s.state
 }
@@ -117,7 +110,7 @@ func (s *Service) Status() (*ResultStatus, error) {
 	return &ResultStatus{
 		NodeInfo:          s.nodeView.NodeInfo(),
 		GenesisHash:       s.blockchain.GenesisHash(),
-		PubKey:            publicKey,
+		PublicKey:         publicKey,
 		LatestBlockHash:   latestBlockHash,
 		LatestBlockHeight: latestHeight,
 		LatestBlockTime:   latestBlockTime,
@@ -157,6 +150,7 @@ func (s *Service) NetInfo() (*ResultNetInfo, error) {
 		return nil, err
 	}
 	return &ResultNetInfo{
+		ThisNode:  s.nodeView.NodeInfo(),
 		Listening: listening,
 		Listeners: listeners,
 		Peers:     peers.Peers,
@@ -242,7 +236,7 @@ func (s *Service) GetAccountHumanReadable(address crypto.Address) (*ResultGetAcc
 	if acc == nil {
 		return &ResultGetAccountHumanReadable{}, nil
 	}
-	perms, err := permission.BasePermissionsToStringList(acc.Permissions().Base)
+	perms := permission.BasePermissionsToStringList(acc.Permissions().Base)
 	if acc == nil {
 		return &ResultGetAccountHumanReadable{}, nil
 	}
@@ -323,10 +317,11 @@ func (s *Service) ListBlocks(minHeight, maxHeight uint64) (*ResultListBlocks, er
 }
 
 func (s *Service) ListValidators() (*ResultListValidators, error) {
-	concreteValidators := make([]*acm.ConcreteValidator, 0, s.blockchain.NumValidators())
-	s.blockchain.IterateValidators(func(id crypto.Addressable, power *big.Int) (stop bool) {
-		concreteValidators = append(concreteValidators, &acm.ConcreteValidator{
-			Address:   id.Address(),
+	validators := make([]*validator.Validator, 0, s.blockchain.NumValidators())
+	s.blockchain.Validators().Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) {
+		address := id.Address()
+		validators = append(validators, &validator.Validator{
+			Address:   &address,
 			PublicKey: id.PublicKey(),
 			Power:     power.Uint64(),
 		})
@@ -334,7 +329,7 @@ func (s *Service) ListValidators() (*ResultListValidators, error) {
 	})
 	return &ResultListValidators{
 		BlockHeight:         s.blockchain.LastBlockHeight(),
-		BondedValidators:    concreteValidators,
+		BondedValidators:    validators,
 		UnbondingValidators: nil,
 	}, nil
 }
diff --git a/txs/amino_codec.go b/txs/amino_codec.go
index 9d85480b..2ff42331 100644
--- a/txs/amino_codec.go
+++ b/txs/amino_codec.go
@@ -18,9 +18,9 @@ func NewAminoCodec() *aminoCodec {
 	registerTx(cdc, &payload.CallTx{})
 	registerTx(cdc, &payload.BondTx{})
 	registerTx(cdc, &payload.UnbondTx{})
-	registerTx(cdc, &payload.PermissionsTx{})
+	registerTx(cdc, &payload.PermsTx{})
 	registerTx(cdc, &payload.NameTx{})
-	registerTx(cdc, &payload.GovernanceTx{})
+	registerTx(cdc, &payload.GovTx{})
 	return &aminoCodec{cdc}
 }
 
diff --git a/txs/payload/bond_tx.go b/txs/payload/bond_tx.go
index 59585b6e..f81b2133 100644
--- a/txs/payload/bond_tx.go
+++ b/txs/payload/bond_tx.go
@@ -54,3 +54,9 @@ func (tx *BondTx) AddOutput(addr crypto.Address, amt uint64) error {
 	})
 	return nil
 }
+
+func (tx *BondTx) Any() *Any {
+	return &Any{
+		BondTx: tx,
+	}
+}
diff --git a/txs/payload/call_tx.go b/txs/payload/call_tx.go
index 68638de3..9855e296 100644
--- a/txs/payload/call_tx.go
+++ b/txs/payload/call_tx.go
@@ -59,3 +59,9 @@ func (tx *CallTx) CreatesContractAddress() *crypto.Address {
 	address := crypto.NewContractAddress(tx.Input.Address, tx.Input.Sequence)
 	return &address
 }
+
+func (tx *CallTx) Any() *Any {
+	return &Any{
+		CallTx: tx,
+	}
+}
diff --git a/txs/payload/gov_tx.go b/txs/payload/gov_tx.go
new file mode 100644
index 00000000..eb4e5a1d
--- /dev/null
+++ b/txs/payload/gov_tx.go
@@ -0,0 +1,23 @@
+package payload
+
+import (
+	"fmt"
+)
+
+func (tx *GovTx) Type() Type {
+	return TypeGovernance
+}
+
+func (tx *GovTx) GetInputs() []*TxInput {
+	return tx.Inputs
+}
+
+func (tx *GovTx) String() string {
+	return fmt.Sprintf("GovTx{%v -> %v}", tx.Inputs, tx.AccountUpdates)
+}
+
+func (tx *GovTx) Any() *Any {
+	return &Any{
+		GovTx: tx,
+	}
+}
diff --git a/txs/payload/governance_tx.go b/txs/payload/governance_tx.go
deleted file mode 100644
index 5f8bfdeb..00000000
--- a/txs/payload/governance_tx.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package payload
-
-import (
-	"fmt"
-)
-
-func (tx *GovernanceTx) Type() Type {
-	return TypeGovernance
-}
-
-func (tx *GovernanceTx) GetInputs() []*TxInput {
-	return tx.Inputs
-}
-
-func (tx *GovernanceTx) String() string {
-	return fmt.Sprintf("GovernanceTx{%v -> %v}", tx.Inputs, tx.AccountUpdates)
-}
diff --git a/txs/payload/name_tx.go b/txs/payload/name_tx.go
index 334fa6df..13f85318 100644
--- a/txs/payload/name_tx.go
+++ b/txs/payload/name_tx.go
@@ -47,3 +47,9 @@ func (tx *NameTx) GetInputs() []*TxInput {
 func (tx *NameTx) String() string {
 	return fmt.Sprintf("NameTx{%v -> %s: %s}", tx.Input, tx.Name, tx.Data)
 }
+
+func (tx *NameTx) Any() *Any {
+	return &Any{
+		NameTx: tx,
+	}
+}
diff --git a/txs/payload/payload.go b/txs/payload/payload.go
index f415d8f8..d55a8cad 100644
--- a/txs/payload/payload.go
+++ b/txs/payload/payload.go
@@ -1,5 +1,7 @@
 package payload
 
+import "fmt"
+
 /*
 Payload (Transaction) is an atomic operation on the ledger state.
 
@@ -13,7 +15,7 @@ Validation Txs:
  - UnbondTx       Validator leaves
 
 Admin Txs:
- - PermissionsTx
+ - PermsTx
 */
 
 type Type uint32
@@ -42,8 +44,8 @@ var nameFromType = map[Type]string{
 	TypeName:        "NameTx",
 	TypeBond:        "BondTx",
 	TypeUnbond:      "UnbondTx",
-	TypePermissions: "PermissionsTx",
-	TypeGovernance:  "GovernanceTx",
+	TypePermissions: "PermsTx",
+	TypeGovernance:  "GovTx",
 }
 
 var typeFromName = make(map[string]Type)
@@ -88,24 +90,50 @@ type Payload interface {
 	String() string
 	GetInputs() []*TxInput
 	Type() Type
+	Any() *Any
 	// The serialised size in bytes
 	Size() int
 }
 
-func New(txType Type) Payload {
+type UnknownTx struct {
+}
+
+func (UnknownTx) String() string {
+	panic("implement me")
+}
+
+func (UnknownTx) GetInputs() []*TxInput {
+	panic("implement me")
+}
+
+func (UnknownTx) Type() Type {
+	panic("implement me")
+}
+
+func (UnknownTx) Any() *Any {
+	panic("implement me")
+}
+
+func (UnknownTx) Size() int {
+	panic("implement me")
+}
+
+func New(txType Type) (Payload, error) {
 	switch txType {
 	case TypeSend:
-		return &SendTx{}
+		return &SendTx{}, nil
 	case TypeCall:
-		return &CallTx{}
+		return &CallTx{}, nil
 	case TypeName:
-		return &NameTx{}
+		return &NameTx{}, nil
 	case TypeBond:
-		return &BondTx{}
+		return &BondTx{}, nil
 	case TypeUnbond:
-		return &UnbondTx{}
+		return &UnbondTx{}, nil
 	case TypePermissions:
-		return &PermissionsTx{}
+		return &PermsTx{}, nil
+	case TypeGovernance:
+		return &GovTx{}, nil
 	}
-	return nil
+	return nil, fmt.Errorf("unknown payload type: %d", txType)
 }
diff --git a/txs/payload/payload.pb.go b/txs/payload/payload.pb.go
index a5e27c74..f1e5755e 100644
--- a/txs/payload/payload.pb.go
+++ b/txs/payload/payload.pb.go
@@ -8,16 +8,16 @@
 		payload.proto
 
 	It has these top-level messages:
-		AnyPayload
+		Any
 		TxInput
 		TxOutput
 		CallTx
 		SendTx
-		PermissionsTx
+		PermsTx
 		NameTx
 		BondTx
 		UnbondTx
-		GovernanceTx
+		GovTx
 */
 package payload
 
@@ -46,56 +46,72 @@ var _ = math.Inf
 // proto package needs to be updated.
 const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
 
-type AnyPayload struct {
-	CallTx        *CallTx        `protobuf:"bytes,1,opt,name=CallTx" json:"CallTx,omitempty"`
-	SendTx        *SendTx        `protobuf:"bytes,2,opt,name=SendTx" json:"SendTx,omitempty"`
-	NameTx        *NameTx        `protobuf:"bytes,3,opt,name=NameTx" json:"NameTx,omitempty"`
-	PermissionsTx *PermissionsTx `protobuf:"bytes,4,opt,name=PermissionsTx" json:"PermissionsTx,omitempty"`
-	GovernanceTx  *GovernanceTx  `protobuf:"bytes,5,opt,name=GovernanceTx" json:"GovernanceTx,omitempty"`
+type Any struct {
+	CallTx   *CallTx   `protobuf:"bytes,1,opt,name=CallTx" json:"CallTx,omitempty"`
+	SendTx   *SendTx   `protobuf:"bytes,2,opt,name=SendTx" json:"SendTx,omitempty"`
+	NameTx   *NameTx   `protobuf:"bytes,3,opt,name=NameTx" json:"NameTx,omitempty"`
+	PermsTx  *PermsTx  `protobuf:"bytes,4,opt,name=PermsTx" json:"PermsTx,omitempty"`
+	GovTx    *GovTx    `protobuf:"bytes,5,opt,name=GovTx" json:"GovTx,omitempty"`
+	BondTx   *BondTx   `protobuf:"bytes,6,opt,name=BondTx" json:"BondTx,omitempty"`
+	UnbondTx *UnbondTx `protobuf:"bytes,7,opt,name=UnbondTx" json:"UnbondTx,omitempty"`
 }
 
-func (m *AnyPayload) Reset()                    { *m = AnyPayload{} }
-func (m *AnyPayload) String() string            { return proto.CompactTextString(m) }
-func (*AnyPayload) ProtoMessage()               {}
-func (*AnyPayload) Descriptor() ([]byte, []int) { return fileDescriptorPayload, []int{0} }
+func (m *Any) Reset()                    { *m = Any{} }
+func (m *Any) String() string            { return proto.CompactTextString(m) }
+func (*Any) ProtoMessage()               {}
+func (*Any) Descriptor() ([]byte, []int) { return fileDescriptorPayload, []int{0} }
 
-func (m *AnyPayload) GetCallTx() *CallTx {
+func (m *Any) GetCallTx() *CallTx {
 	if m != nil {
 		return m.CallTx
 	}
 	return nil
 }
 
-func (m *AnyPayload) GetSendTx() *SendTx {
+func (m *Any) GetSendTx() *SendTx {
 	if m != nil {
 		return m.SendTx
 	}
 	return nil
 }
 
-func (m *AnyPayload) GetNameTx() *NameTx {
+func (m *Any) GetNameTx() *NameTx {
 	if m != nil {
 		return m.NameTx
 	}
 	return nil
 }
 
-func (m *AnyPayload) GetPermissionsTx() *PermissionsTx {
+func (m *Any) GetPermsTx() *PermsTx {
 	if m != nil {
-		return m.PermissionsTx
+		return m.PermsTx
 	}
 	return nil
 }
 
-func (m *AnyPayload) GetGovernanceTx() *GovernanceTx {
+func (m *Any) GetGovTx() *GovTx {
 	if m != nil {
-		return m.GovernanceTx
+		return m.GovTx
 	}
 	return nil
 }
 
-func (*AnyPayload) XXX_MessageName() string {
-	return "payload.AnyPayload"
+func (m *Any) GetBondTx() *BondTx {
+	if m != nil {
+		return m.BondTx
+	}
+	return nil
+}
+
+func (m *Any) GetUnbondTx() *UnbondTx {
+	if m != nil {
+		return m.UnbondTx
+	}
+	return nil
+}
+
+func (*Any) XXX_MessageName() string {
+	return "payload.Any"
 }
 
 // An input to a transaction that may carry an Amount as a charge and whose sequence number must be one greater than
@@ -214,33 +230,33 @@ func (*SendTx) XXX_MessageName() string {
 }
 
 // An update to the on-chain permissions
-type PermissionsTx struct {
+type PermsTx struct {
 	// The permission moderator
 	Input *TxInput `protobuf:"bytes,1,opt,name=Input" json:"Input,omitempty"`
 	// The modified permissions
 	PermArgs permission.PermArgs `protobuf:"bytes,2,opt,name=PermArgs" json:"PermArgs"`
 }
 
-func (m *PermissionsTx) Reset()                    { *m = PermissionsTx{} }
-func (*PermissionsTx) ProtoMessage()               {}
-func (*PermissionsTx) Descriptor() ([]byte, []int) { return fileDescriptorPayload, []int{5} }
+func (m *PermsTx) Reset()                    { *m = PermsTx{} }
+func (*PermsTx) ProtoMessage()               {}
+func (*PermsTx) Descriptor() ([]byte, []int) { return fileDescriptorPayload, []int{5} }
 
-func (m *PermissionsTx) GetInput() *TxInput {
+func (m *PermsTx) GetInput() *TxInput {
 	if m != nil {
 		return m.Input
 	}
 	return nil
 }
 
-func (m *PermissionsTx) GetPermArgs() permission.PermArgs {
+func (m *PermsTx) GetPermArgs() permission.PermArgs {
 	if m != nil {
 		return m.PermArgs
 	}
 	return permission.PermArgs{}
 }
 
-func (*PermissionsTx) XXX_MessageName() string {
-	return "payload.PermissionsTx"
+func (*PermsTx) XXX_MessageName() string {
+	return "payload.PermsTx"
 }
 
 // A request to claim a globally unique name across the entire chain with some optional data storage leased for a fee
@@ -318,21 +334,21 @@ func (*UnbondTx) XXX_MessageName() string {
 	return "payload.UnbondTx"
 }
 
-type GovernanceTx struct {
+type GovTx struct {
 	Inputs         []*TxInput              `protobuf:"bytes,1,rep,name=Inputs" json:"Inputs,omitempty"`
 	AccountUpdates []*spec.TemplateAccount `protobuf:"bytes,2,rep,name=AccountUpdates" json:"AccountUpdates,omitempty"`
 }
 
-func (m *GovernanceTx) Reset()                    { *m = GovernanceTx{} }
-func (*GovernanceTx) ProtoMessage()               {}
-func (*GovernanceTx) Descriptor() ([]byte, []int) { return fileDescriptorPayload, []int{9} }
+func (m *GovTx) Reset()                    { *m = GovTx{} }
+func (*GovTx) ProtoMessage()               {}
+func (*GovTx) Descriptor() ([]byte, []int) { return fileDescriptorPayload, []int{9} }
 
-func (*GovernanceTx) XXX_MessageName() string {
-	return "payload.GovernanceTx"
+func (*GovTx) XXX_MessageName() string {
+	return "payload.GovTx"
 }
 func init() {
-	proto.RegisterType((*AnyPayload)(nil), "payload.AnyPayload")
-	golang_proto.RegisterType((*AnyPayload)(nil), "payload.AnyPayload")
+	proto.RegisterType((*Any)(nil), "payload.Any")
+	golang_proto.RegisterType((*Any)(nil), "payload.Any")
 	proto.RegisterType((*TxInput)(nil), "payload.TxInput")
 	golang_proto.RegisterType((*TxInput)(nil), "payload.TxInput")
 	proto.RegisterType((*TxOutput)(nil), "payload.TxOutput")
@@ -341,18 +357,18 @@ func init() {
 	golang_proto.RegisterType((*CallTx)(nil), "payload.CallTx")
 	proto.RegisterType((*SendTx)(nil), "payload.SendTx")
 	golang_proto.RegisterType((*SendTx)(nil), "payload.SendTx")
-	proto.RegisterType((*PermissionsTx)(nil), "payload.PermissionsTx")
-	golang_proto.RegisterType((*PermissionsTx)(nil), "payload.PermissionsTx")
+	proto.RegisterType((*PermsTx)(nil), "payload.PermsTx")
+	golang_proto.RegisterType((*PermsTx)(nil), "payload.PermsTx")
 	proto.RegisterType((*NameTx)(nil), "payload.NameTx")
 	golang_proto.RegisterType((*NameTx)(nil), "payload.NameTx")
 	proto.RegisterType((*BondTx)(nil), "payload.BondTx")
 	golang_proto.RegisterType((*BondTx)(nil), "payload.BondTx")
 	proto.RegisterType((*UnbondTx)(nil), "payload.UnbondTx")
 	golang_proto.RegisterType((*UnbondTx)(nil), "payload.UnbondTx")
-	proto.RegisterType((*GovernanceTx)(nil), "payload.GovernanceTx")
-	golang_proto.RegisterType((*GovernanceTx)(nil), "payload.GovernanceTx")
+	proto.RegisterType((*GovTx)(nil), "payload.GovTx")
+	golang_proto.RegisterType((*GovTx)(nil), "payload.GovTx")
 }
-func (m *AnyPayload) Marshal() (dAtA []byte, err error) {
+func (m *Any) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	dAtA = make([]byte, size)
 	n, err := m.MarshalTo(dAtA)
@@ -362,7 +378,7 @@ func (m *AnyPayload) Marshal() (dAtA []byte, err error) {
 	return dAtA[:n], nil
 }
 
-func (m *AnyPayload) MarshalTo(dAtA []byte) (int, error) {
+func (m *Any) MarshalTo(dAtA []byte) (int, error) {
 	var i int
 	_ = i
 	var l int
@@ -397,26 +413,46 @@ func (m *AnyPayload) MarshalTo(dAtA []byte) (int, error) {
 		}
 		i += n3
 	}
-	if m.PermissionsTx != nil {
+	if m.PermsTx != nil {
 		dAtA[i] = 0x22
 		i++
-		i = encodeVarintPayload(dAtA, i, uint64(m.PermissionsTx.Size()))
-		n4, err := m.PermissionsTx.MarshalTo(dAtA[i:])
+		i = encodeVarintPayload(dAtA, i, uint64(m.PermsTx.Size()))
+		n4, err := m.PermsTx.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
 		i += n4
 	}
-	if m.GovernanceTx != nil {
+	if m.GovTx != nil {
 		dAtA[i] = 0x2a
 		i++
-		i = encodeVarintPayload(dAtA, i, uint64(m.GovernanceTx.Size()))
-		n5, err := m.GovernanceTx.MarshalTo(dAtA[i:])
+		i = encodeVarintPayload(dAtA, i, uint64(m.GovTx.Size()))
+		n5, err := m.GovTx.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
 		i += n5
 	}
+	if m.BondTx != nil {
+		dAtA[i] = 0x32
+		i++
+		i = encodeVarintPayload(dAtA, i, uint64(m.BondTx.Size()))
+		n6, err := m.BondTx.MarshalTo(dAtA[i:])
+		if err != nil {
+			return 0, err
+		}
+		i += n6
+	}
+	if m.UnbondTx != nil {
+		dAtA[i] = 0x3a
+		i++
+		i = encodeVarintPayload(dAtA, i, uint64(m.UnbondTx.Size()))
+		n7, err := m.UnbondTx.MarshalTo(dAtA[i:])
+		if err != nil {
+			return 0, err
+		}
+		i += n7
+	}
 	return i, nil
 }
 
@@ -438,11 +474,11 @@ func (m *TxInput) MarshalTo(dAtA []byte) (int, error) {
 	dAtA[i] = 0xa
 	i++
 	i = encodeVarintPayload(dAtA, i, uint64(m.Address.Size()))
-	n6, err := m.Address.MarshalTo(dAtA[i:])
+	n8, err := m.Address.MarshalTo(dAtA[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n6
+	i += n8
 	if m.Amount != 0 {
 		dAtA[i] = 0x10
 		i++
@@ -474,11 +510,11 @@ func (m *TxOutput) MarshalTo(dAtA []byte) (int, error) {
 	dAtA[i] = 0xa
 	i++
 	i = encodeVarintPayload(dAtA, i, uint64(m.Address.Size()))
-	n7, err := m.Address.MarshalTo(dAtA[i:])
+	n9, err := m.Address.MarshalTo(dAtA[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n7
+	i += n9
 	if m.Amount != 0 {
 		dAtA[i] = 0x10
 		i++
@@ -506,21 +542,21 @@ func (m *CallTx) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0xa
 		i++
 		i = encodeVarintPayload(dAtA, i, uint64(m.Input.Size()))
-		n8, err := m.Input.MarshalTo(dAtA[i:])
+		n10, err := m.Input.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n8
+		i += n10
 	}
 	if m.Address != nil {
 		dAtA[i] = 0x12
 		i++
 		i = encodeVarintPayload(dAtA, i, uint64(m.Address.Size()))
-		n9, err := m.Address.MarshalTo(dAtA[i:])
+		n11, err := m.Address.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n9
+		i += n11
 	}
 	if m.GasLimit != 0 {
 		dAtA[i] = 0x18
@@ -535,11 +571,11 @@ func (m *CallTx) MarshalTo(dAtA []byte) (int, error) {
 	dAtA[i] = 0x2a
 	i++
 	i = encodeVarintPayload(dAtA, i, uint64(m.Data.Size()))
-	n10, err := m.Data.MarshalTo(dAtA[i:])
+	n12, err := m.Data.MarshalTo(dAtA[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n10
+	i += n12
 	return i, nil
 }
 
@@ -585,7 +621,7 @@ func (m *SendTx) MarshalTo(dAtA []byte) (int, error) {
 	return i, nil
 }
 
-func (m *PermissionsTx) Marshal() (dAtA []byte, err error) {
+func (m *PermsTx) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	dAtA = make([]byte, size)
 	n, err := m.MarshalTo(dAtA)
@@ -595,7 +631,7 @@ func (m *PermissionsTx) Marshal() (dAtA []byte, err error) {
 	return dAtA[:n], nil
 }
 
-func (m *PermissionsTx) MarshalTo(dAtA []byte) (int, error) {
+func (m *PermsTx) MarshalTo(dAtA []byte) (int, error) {
 	var i int
 	_ = i
 	var l int
@@ -604,20 +640,20 @@ func (m *PermissionsTx) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0xa
 		i++
 		i = encodeVarintPayload(dAtA, i, uint64(m.Input.Size()))
-		n11, err := m.Input.MarshalTo(dAtA[i:])
+		n13, err := m.Input.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n11
+		i += n13
 	}
 	dAtA[i] = 0x12
 	i++
 	i = encodeVarintPayload(dAtA, i, uint64(m.PermArgs.Size()))
-	n12, err := m.PermArgs.MarshalTo(dAtA[i:])
+	n14, err := m.PermArgs.MarshalTo(dAtA[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n12
+	i += n14
 	return i, nil
 }
 
@@ -640,11 +676,11 @@ func (m *NameTx) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0xa
 		i++
 		i = encodeVarintPayload(dAtA, i, uint64(m.Input.Size()))
-		n13, err := m.Input.MarshalTo(dAtA[i:])
+		n15, err := m.Input.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n13
+		i += n15
 	}
 	if len(m.Name) > 0 {
 		dAtA[i] = 0x12
@@ -727,20 +763,20 @@ func (m *UnbondTx) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0xa
 		i++
 		i = encodeVarintPayload(dAtA, i, uint64(m.Input.Size()))
-		n14, err := m.Input.MarshalTo(dAtA[i:])
+		n16, err := m.Input.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n14
+		i += n16
 	}
 	dAtA[i] = 0x12
 	i++
 	i = encodeVarintPayload(dAtA, i, uint64(m.Address.Size()))
-	n15, err := m.Address.MarshalTo(dAtA[i:])
+	n17, err := m.Address.MarshalTo(dAtA[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n15
+	i += n17
 	if m.Height != 0 {
 		dAtA[i] = 0x18
 		i++
@@ -749,7 +785,7 @@ func (m *UnbondTx) MarshalTo(dAtA []byte) (int, error) {
 	return i, nil
 }
 
-func (m *GovernanceTx) Marshal() (dAtA []byte, err error) {
+func (m *GovTx) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	dAtA = make([]byte, size)
 	n, err := m.MarshalTo(dAtA)
@@ -759,7 +795,7 @@ func (m *GovernanceTx) Marshal() (dAtA []byte, err error) {
 	return dAtA[:n], nil
 }
 
-func (m *GovernanceTx) MarshalTo(dAtA []byte) (int, error) {
+func (m *GovTx) MarshalTo(dAtA []byte) (int, error) {
 	var i int
 	_ = i
 	var l int
@@ -800,7 +836,7 @@ func encodeVarintPayload(dAtA []byte, offset int, v uint64) int {
 	dAtA[offset] = uint8(v)
 	return offset + 1
 }
-func (m *AnyPayload) Size() (n int) {
+func (m *Any) Size() (n int) {
 	var l int
 	_ = l
 	if m.CallTx != nil {
@@ -815,12 +851,20 @@ func (m *AnyPayload) Size() (n int) {
 		l = m.NameTx.Size()
 		n += 1 + l + sovPayload(uint64(l))
 	}
-	if m.PermissionsTx != nil {
-		l = m.PermissionsTx.Size()
+	if m.PermsTx != nil {
+		l = m.PermsTx.Size()
 		n += 1 + l + sovPayload(uint64(l))
 	}
-	if m.GovernanceTx != nil {
-		l = m.GovernanceTx.Size()
+	if m.GovTx != nil {
+		l = m.GovTx.Size()
+		n += 1 + l + sovPayload(uint64(l))
+	}
+	if m.BondTx != nil {
+		l = m.BondTx.Size()
+		n += 1 + l + sovPayload(uint64(l))
+	}
+	if m.UnbondTx != nil {
+		l = m.UnbondTx.Size()
 		n += 1 + l + sovPayload(uint64(l))
 	}
 	return n
@@ -891,7 +935,7 @@ func (m *SendTx) Size() (n int) {
 	return n
 }
 
-func (m *PermissionsTx) Size() (n int) {
+func (m *PermsTx) Size() (n int) {
 	var l int
 	_ = l
 	if m.Input != nil {
@@ -957,7 +1001,7 @@ func (m *UnbondTx) Size() (n int) {
 	return n
 }
 
-func (m *GovernanceTx) Size() (n int) {
+func (m *GovTx) Size() (n int) {
 	var l int
 	_ = l
 	if len(m.Inputs) > 0 {
@@ -988,7 +1032,7 @@ func sovPayload(x uint64) (n int) {
 func sozPayload(x uint64) (n int) {
 	return sovPayload(uint64((x << 1) ^ uint64((int64(x) >> 63))))
 }
-func (m *AnyPayload) Unmarshal(dAtA []byte) error {
+func (m *Any) Unmarshal(dAtA []byte) error {
 	l := len(dAtA)
 	iNdEx := 0
 	for iNdEx < l {
@@ -1011,10 +1055,10 @@ func (m *AnyPayload) Unmarshal(dAtA []byte) error {
 		fieldNum := int32(wire >> 3)
 		wireType := int(wire & 0x7)
 		if wireType == 4 {
-			return fmt.Errorf("proto: AnyPayload: wiretype end group for non-group")
+			return fmt.Errorf("proto: Any: wiretype end group for non-group")
 		}
 		if fieldNum <= 0 {
-			return fmt.Errorf("proto: AnyPayload: illegal tag %d (wire type %d)", fieldNum, wire)
+			return fmt.Errorf("proto: Any: illegal tag %d (wire type %d)", fieldNum, wire)
 		}
 		switch fieldNum {
 		case 1:
@@ -1118,7 +1162,7 @@ func (m *AnyPayload) Unmarshal(dAtA []byte) error {
 			iNdEx = postIndex
 		case 4:
 			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field PermissionsTx", wireType)
+				return fmt.Errorf("proto: wrong wireType = %d for field PermsTx", wireType)
 			}
 			var msglen int
 			for shift := uint(0); ; shift += 7 {
@@ -1142,16 +1186,82 @@ func (m *AnyPayload) Unmarshal(dAtA []byte) error {
 			if postIndex > l {
 				return io.ErrUnexpectedEOF
 			}
-			if m.PermissionsTx == nil {
-				m.PermissionsTx = &PermissionsTx{}
+			if m.PermsTx == nil {
+				m.PermsTx = &PermsTx{}
 			}
-			if err := m.PermissionsTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+			if err := m.PermsTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 				return err
 			}
 			iNdEx = postIndex
 		case 5:
 			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field GovernanceTx", wireType)
+				return fmt.Errorf("proto: wrong wireType = %d for field GovTx", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowPayload
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthPayload
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.GovTx == nil {
+				m.GovTx = &GovTx{}
+			}
+			if err := m.GovTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 6:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field BondTx", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowPayload
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthPayload
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.BondTx == nil {
+				m.BondTx = &BondTx{}
+			}
+			if err := m.BondTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 7:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field UnbondTx", wireType)
 			}
 			var msglen int
 			for shift := uint(0); ; shift += 7 {
@@ -1175,10 +1285,10 @@ func (m *AnyPayload) Unmarshal(dAtA []byte) error {
 			if postIndex > l {
 				return io.ErrUnexpectedEOF
 			}
-			if m.GovernanceTx == nil {
-				m.GovernanceTx = &GovernanceTx{}
+			if m.UnbondTx == nil {
+				m.UnbondTx = &UnbondTx{}
 			}
-			if err := m.GovernanceTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+			if err := m.UnbondTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 				return err
 			}
 			iNdEx = postIndex
@@ -1715,7 +1825,7 @@ func (m *SendTx) Unmarshal(dAtA []byte) error {
 	}
 	return nil
 }
-func (m *PermissionsTx) Unmarshal(dAtA []byte) error {
+func (m *PermsTx) Unmarshal(dAtA []byte) error {
 	l := len(dAtA)
 	iNdEx := 0
 	for iNdEx < l {
@@ -1738,10 +1848,10 @@ func (m *PermissionsTx) Unmarshal(dAtA []byte) error {
 		fieldNum := int32(wire >> 3)
 		wireType := int(wire & 0x7)
 		if wireType == 4 {
-			return fmt.Errorf("proto: PermissionsTx: wiretype end group for non-group")
+			return fmt.Errorf("proto: PermsTx: wiretype end group for non-group")
 		}
 		if fieldNum <= 0 {
-			return fmt.Errorf("proto: PermissionsTx: illegal tag %d (wire type %d)", fieldNum, wire)
+			return fmt.Errorf("proto: PermsTx: illegal tag %d (wire type %d)", fieldNum, wire)
 		}
 		switch fieldNum {
 		case 1:
@@ -2232,7 +2342,7 @@ func (m *UnbondTx) Unmarshal(dAtA []byte) error {
 	}
 	return nil
 }
-func (m *GovernanceTx) Unmarshal(dAtA []byte) error {
+func (m *GovTx) Unmarshal(dAtA []byte) error {
 	l := len(dAtA)
 	iNdEx := 0
 	for iNdEx < l {
@@ -2255,10 +2365,10 @@ func (m *GovernanceTx) Unmarshal(dAtA []byte) error {
 		fieldNum := int32(wire >> 3)
 		wireType := int(wire & 0x7)
 		if wireType == 4 {
-			return fmt.Errorf("proto: GovernanceTx: wiretype end group for non-group")
+			return fmt.Errorf("proto: GovTx: wiretype end group for non-group")
 		}
 		if fieldNum <= 0 {
-			return fmt.Errorf("proto: GovernanceTx: illegal tag %d (wire type %d)", fieldNum, wire)
+			return fmt.Errorf("proto: GovTx: illegal tag %d (wire type %d)", fieldNum, wire)
 		}
 		switch fieldNum {
 		case 1:
@@ -2453,46 +2563,47 @@ func init() { proto.RegisterFile("payload.proto", fileDescriptorPayload) }
 func init() { golang_proto.RegisterFile("payload.proto", fileDescriptorPayload) }
 
 var fileDescriptorPayload = []byte{
-	// 652 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0xbf, 0x6f, 0xd3, 0x40,
-	0x14, 0xee, 0x35, 0x6e, 0x62, 0x8e, 0x16, 0xca, 0x89, 0x56, 0x51, 0x86, 0x04, 0x75, 0x80, 0x22,
-	0xa8, 0x83, 0xf8, 0x25, 0x51, 0x21, 0xa1, 0xb8, 0x88, 0xb6, 0x08, 0x85, 0xea, 0xea, 0x2e, 0x6c,
-	0xfe, 0x71, 0x38, 0x16, 0xb1, 0xcf, 0xd8, 0x67, 0xb0, 0x37, 0x36, 0xd8, 0x59, 0x18, 0x3b, 0xf0,
-	0x87, 0x30, 0x66, 0x64, 0x66, 0xa8, 0x50, 0xfa, 0x67, 0xb0, 0xa0, 0x3b, 0x9f, 0x5d, 0x27, 0x40,
-	0x95, 0x82, 0xc4, 0x76, 0xef, 0x7d, 0xdf, 0xbb, 0xf7, 0xde, 0x77, 0xef, 0xd9, 0x70, 0x29, 0x34,
-	0xb3, 0x21, 0x35, 0x1d, 0x2d, 0x8c, 0x28, 0xa3, 0xa8, 0x21, 0xcd, 0xd6, 0x86, 0xeb, 0xb1, 0x41,
-	0x62, 0x69, 0x36, 0xf5, 0xbb, 0x2e, 0x75, 0x69, 0x57, 0xe0, 0x56, 0xf2, 0x52, 0x58, 0xc2, 0x10,
-	0xa7, 0x3c, 0xae, 0xb5, 0x1c, 0x92, 0xc8, 0xf7, 0xe2, 0xd8, 0xa3, 0x81, 0xf4, 0xc0, 0x38, 0x24,
-	0x76, 0x7e, 0x5e, 0x7b, 0x37, 0x0f, 0x61, 0x2f, 0xc8, 0xf6, 0xf2, 0xbb, 0xd1, 0x35, 0x58, 0xdf,
-	0x32, 0x87, 0x43, 0x23, 0x6d, 0x82, 0x2b, 0x60, 0xfd, 0xfc, 0xed, 0x8b, 0x5a, 0x51, 0x44, 0xee,
-	0xc6, 0x12, 0xe6, 0xc4, 0x7d, 0x12, 0x38, 0x46, 0xda, 0x9c, 0x9f, 0x22, 0xe6, 0x6e, 0x2c, 0x61,
-	0x4e, 0xec, 0x9b, 0x3e, 0x31, 0xd2, 0x66, 0x6d, 0x8a, 0x98, 0xbb, 0xb1, 0x84, 0xd1, 0x43, 0xb8,
-	0xb4, 0x57, 0x56, 0x1a, 0x1b, 0x69, 0x53, 0x11, 0xfc, 0xd5, 0x92, 0x3f, 0x81, 0xe2, 0x49, 0x32,
-	0x7a, 0x00, 0x17, 0xb7, 0xe9, 0x1b, 0x12, 0x05, 0x66, 0x60, 0xf3, 0x64, 0x0b, 0x22, 0x78, 0xa5,
-	0x0c, 0xae, 0x82, 0x78, 0x82, 0xba, 0xf6, 0x11, 0xc0, 0x86, 0x91, 0xee, 0x06, 0x61, 0xc2, 0x50,
-	0x1f, 0x36, 0x7a, 0x8e, 0x13, 0x91, 0x38, 0x16, 0x02, 0x2c, 0xea, 0x77, 0x47, 0x47, 0x9d, 0xb9,
-	0x6f, 0x47, 0x9d, 0x9b, 0x15, 0xd1, 0x07, 0x59, 0x48, 0xa2, 0x21, 0x71, 0x5c, 0x12, 0x75, 0xad,
-	0x24, 0x8a, 0xe8, 0xdb, 0xae, 0x1d, 0x65, 0x21, 0xa3, 0x9a, 0x8c, 0xc5, 0xc5, 0x25, 0x68, 0x15,
-	0xd6, 0x7b, 0x3e, 0x4d, 0x02, 0x26, 0x64, 0x52, 0xb0, 0xb4, 0x50, 0x0b, 0xaa, 0xfb, 0xe4, 0x75,
-	0x42, 0x02, 0x9b, 0x08, 0x5d, 0x14, 0x5c, 0xda, 0x9b, 0xca, 0xa7, 0xc3, 0xce, 0xdc, 0x5a, 0x0a,
-	0x55, 0x23, 0x7d, 0x9e, 0xb0, 0xff, 0x58, 0x95, 0xcc, 0xfc, 0x03, 0x14, 0x43, 0x80, 0xae, 0xc2,
-	0x05, 0xa1, 0x8b, 0x9c, 0x86, 0xe5, 0x52, 0x4e, 0xa9, 0x17, 0xce, 0x61, 0xf4, 0xf4, 0xa4, 0xc0,
-	0x79, 0x51, 0xe0, 0xad, 0xbf, 0x2f, 0xae, 0x05, 0xd5, 0x6d, 0x33, 0x7e, 0xe6, 0xf9, 0x1e, 0x2b,
-	0xa4, 0x29, 0x6c, 0xb4, 0x0c, 0x6b, 0x4f, 0x08, 0x11, 0x93, 0xa1, 0x60, 0x7e, 0x44, 0xbb, 0x50,
-	0x79, 0x6c, 0x32, 0x53, 0xbc, 0xf7, 0xa2, 0x7e, 0x4f, 0xea, 0xb2, 0x71, 0x7a, 0x6a, 0xcb, 0x0b,
-	0xcc, 0x28, 0xd3, 0x76, 0x48, 0xaa, 0x67, 0x8c, 0xc4, 0x58, 0x5c, 0x21, 0xbb, 0xf7, 0x8a, 0xc1,
-	0x46, 0xeb, 0xb0, 0x2e, 0xba, 0xe3, 0xa2, 0xd7, 0x7e, 0xdb, 0xbd, 0xc4, 0xd1, 0x0d, 0xd8, 0xc8,
-	0x5f, 0x8a, 0xb7, 0xcf, 0xa9, 0x97, 0x2a, 0xd4, 0x1c, 0xc1, 0x05, 0x63, 0x53, 0xfd, 0x70, 0xd8,
-	0x99, 0x13, 0xa9, 0x92, 0xa9, 0x89, 0x9f, 0x59, 0xee, 0xfb, 0x50, 0xe5, 0x81, 0xbd, 0xc8, 0x8d,
-	0xe5, 0xfa, 0x5d, 0xd6, 0x2a, 0x5b, 0x5e, 0x60, 0xba, 0xc2, 0xe5, 0xc0, 0x25, 0x57, 0x76, 0x18,
-	0x16, 0x1b, 0x39, 0x73, 0x3e, 0x04, 0x15, 0x1e, 0x21, 0x72, 0x9d, 0xc3, 0xe2, 0xcc, 0x7d, 0x42,
-	0xf8, 0x5a, 0xee, 0xe3, 0xe7, 0x5f, 0x9f, 0x47, 0x66, 0x7c, 0x05, 0xeb, 0x3a, 0x3d, 0xa3, 0xa6,
-	0x1b, 0x50, 0x3d, 0x08, 0x2c, 0x1e, 0x45, 0xff, 0x2c, 0x6a, 0x49, 0xa9, 0xa8, 0xfa, 0x19, 0x94,
-	0x91, 0xb3, 0x77, 0xd8, 0x9f, 0x1e, 0xe0, 0x7f, 0xdf, 0xb0, 0x1d, 0xe2, 0xb9, 0x83, 0x62, 0x84,
-	0xa5, 0x55, 0x29, 0xf3, 0x3d, 0x98, 0xfc, 0x62, 0x9d, 0x41, 0x9a, 0x2d, 0x78, 0xa1, 0x67, 0xdb,
-	0x7c, 0x63, 0x0f, 0x42, 0xc7, 0x64, 0xa4, 0x98, 0xba, 0x15, 0x4d, 0x7c, 0xd8, 0x0d, 0xe2, 0x87,
-	0x43, 0x93, 0x11, 0xc9, 0x11, 0x53, 0x00, 0xf0, 0x54, 0xc8, 0x49, 0x25, 0xfa, 0xa3, 0xd1, 0xb8,
-	0x0d, 0xbe, 0x8e, 0xdb, 0xe0, 0xfb, 0xb8, 0x0d, 0xbe, 0x1c, 0xb7, 0xc1, 0xe8, 0xb8, 0x0d, 0x5e,
-	0x5c, 0x3f, 0xbd, 0x71, 0x96, 0xc6, 0x5d, 0x59, 0x9f, 0x55, 0x17, 0xbf, 0x92, 0x3b, 0x3f, 0x03,
-	0x00, 0x00, 0xff, 0xff, 0xac, 0xa5, 0xe3, 0x1c, 0xb1, 0x06, 0x00, 0x00,
+	// 665 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0x3b, 0x6f, 0xd4, 0x40,
+	0x10, 0xce, 0xe6, 0x9c, 0xbb, 0x63, 0x09, 0x21, 0xac, 0x00, 0x9d, 0xae, 0xb8, 0x43, 0x11, 0x82,
+	0xf0, 0x88, 0x0f, 0xf1, 0x2a, 0xd2, 0xa0, 0xbb, 0x20, 0x92, 0x20, 0x14, 0xd0, 0xc6, 0x69, 0xe8,
+	0xfc, 0x58, 0x1c, 0x8b, 0xb3, 0xd7, 0xd8, 0x6b, 0xb0, 0x3b, 0x4a, 0x7a, 0x1a, 0xca, 0x14, 0x54,
+	0xfc, 0x0a, 0xca, 0x94, 0xd4, 0x14, 0x11, 0x4a, 0x7e, 0x06, 0x0d, 0xda, 0xf1, 0xae, 0xef, 0x38,
+	0x20, 0xba, 0x80, 0x44, 0xb7, 0x33, 0xdf, 0xb7, 0x9e, 0x99, 0x6f, 0x66, 0xd6, 0xf8, 0x4c, 0x6c,
+	0x17, 0x43, 0x6e, 0x7b, 0x66, 0x9c, 0x70, 0xc1, 0x49, 0x43, 0x99, 0xed, 0x15, 0x3f, 0x10, 0xbb,
+	0x99, 0x63, 0xba, 0x3c, 0xec, 0xf9, 0xdc, 0xe7, 0x3d, 0xc0, 0x9d, 0xec, 0x05, 0x58, 0x60, 0xc0,
+	0xa9, 0xbc, 0xd7, 0x5e, 0x8c, 0x59, 0x12, 0x06, 0x69, 0x1a, 0xf0, 0x48, 0x79, 0x70, 0x1a, 0x33,
+	0xb7, 0x3c, 0x2f, 0x7d, 0x9a, 0xc5, 0xb5, 0x7e, 0x54, 0x90, 0xab, 0xb8, 0xbe, 0x66, 0x0f, 0x87,
+	0x56, 0xde, 0x42, 0x97, 0xd0, 0xf2, 0xe9, 0xdb, 0x67, 0x4d, 0x1d, 0xbd, 0x74, 0x53, 0x05, 0x4b,
+	0xe2, 0x36, 0x8b, 0x3c, 0x2b, 0x6f, 0xcd, 0x4e, 0x10, 0x4b, 0x37, 0x55, 0xb0, 0x24, 0x6e, 0xd9,
+	0x21, 0xb3, 0xf2, 0x56, 0x6d, 0x82, 0x58, 0xba, 0xa9, 0x82, 0xc9, 0x75, 0xdc, 0x78, 0xc6, 0x92,
+	0x30, 0xb5, 0xf2, 0x96, 0x01, 0xcc, 0xc5, 0x8a, 0xa9, 0xfc, 0x54, 0x13, 0xc8, 0x65, 0x3c, 0xb7,
+	0xce, 0x5f, 0x5b, 0x79, 0x6b, 0x0e, 0x98, 0x0b, 0x15, 0x13, 0xbc, 0xb4, 0x04, 0x65, 0xe8, 0x01,
+	0x87, 0x1c, 0xeb, 0x13, 0xa1, 0x4b, 0x37, 0x55, 0x30, 0x59, 0xc1, 0xcd, 0x9d, 0xc8, 0x29, 0xa9,
+	0x0d, 0xa0, 0x9e, 0xab, 0xa8, 0x1a, 0xa0, 0x15, 0x65, 0xe9, 0x3d, 0xc2, 0x0d, 0x2b, 0xdf, 0x8c,
+	0xe2, 0x4c, 0x90, 0x2d, 0xdc, 0xe8, 0x7b, 0x5e, 0xc2, 0xd2, 0x14, 0x14, 0x9b, 0x1f, 0xdc, 0xdd,
+	0x3f, 0xe8, 0xce, 0x7c, 0x3d, 0xe8, 0xde, 0x1c, 0x6b, 0xcf, 0x6e, 0x11, 0xb3, 0x64, 0xc8, 0x3c,
+	0x9f, 0x25, 0x3d, 0x27, 0x4b, 0x12, 0xfe, 0xa6, 0xe7, 0x26, 0x45, 0x2c, 0xb8, 0xa9, 0xee, 0x52,
+	0xfd, 0x11, 0x72, 0x11, 0xd7, 0xfb, 0x21, 0xcf, 0x22, 0x01, 0xba, 0x1a, 0x54, 0x59, 0xa4, 0x8d,
+	0x9b, 0xdb, 0xec, 0x55, 0xc6, 0x22, 0x97, 0x81, 0x90, 0x06, 0xad, 0xec, 0x55, 0xe3, 0xc3, 0x5e,
+	0x77, 0x66, 0x29, 0xc7, 0x4d, 0x2b, 0x7f, 0x9a, 0x89, 0xff, 0x98, 0x95, 0x8a, 0xfc, 0x1d, 0xe9,
+	0xa9, 0x21, 0x57, 0xf0, 0x1c, 0xe8, 0xa2, 0xc6, 0x67, 0xd4, 0x42, 0xa5, 0x17, 0x2d, 0x61, 0xf2,
+	0x78, 0x94, 0xe0, 0x2c, 0x24, 0x78, 0xeb, 0xef, 0x93, 0x6b, 0xe3, 0xe6, 0xba, 0x9d, 0x3e, 0x09,
+	0xc2, 0x40, 0x68, 0x69, 0xb4, 0x4d, 0x16, 0x71, 0xed, 0x11, 0x63, 0x30, 0x50, 0x06, 0x95, 0x47,
+	0xb2, 0x89, 0x8d, 0x87, 0xb6, 0xb0, 0x61, 0x72, 0xe6, 0x07, 0xf7, 0x94, 0x2e, 0x2b, 0xc7, 0x87,
+	0x76, 0x82, 0xc8, 0x4e, 0x0a, 0x73, 0x83, 0xe5, 0x83, 0x42, 0xb0, 0x94, 0xc2, 0x27, 0x54, 0xf5,
+	0x81, 0xde, 0x04, 0xb2, 0x8c, 0xeb, 0x50, 0x9d, 0x14, 0xbd, 0xf6, 0xdb, 0xea, 0x15, 0x4e, 0x6e,
+	0xe0, 0x46, 0xd9, 0x29, 0x59, 0x7e, 0xed, 0xa7, 0x79, 0xd3, 0x3d, 0xa4, 0x9a, 0xb1, 0xda, 0x7c,
+	0xb7, 0xd7, 0x9d, 0x81, 0x50, 0xbc, 0x5a, 0x91, 0xa9, 0x85, 0xbe, 0x8f, 0x9b, 0xf2, 0x4a, 0x3f,
+	0xf1, 0x53, 0xb5, 0xa9, 0xe7, 0xcd, 0xb1, 0x97, 0x40, 0x63, 0x03, 0x43, 0x0a, 0x41, 0x2b, 0xae,
+	0xaa, 0x2d, 0xd6, 0xcb, 0x3b, 0x75, 0x3c, 0x82, 0x0d, 0x79, 0x03, 0x62, 0x9d, 0xa2, 0x70, 0x96,
+	0x3e, 0x90, 0xbc, 0x56, 0xfa, 0xe4, 0xf9, 0xd7, 0xc6, 0xa8, 0x88, 0x2f, 0xf5, 0xce, 0x9e, 0x40,
+	0xcd, 0xd1, 0xfa, 0xf2, 0x3f, 0xcb, 0x59, 0x51, 0xc6, 0xf4, 0xfc, 0x88, 0x46, 0x8b, 0x3f, 0x75,
+	0x85, 0x5b, 0x93, 0xa3, 0xfb, 0xef, 0xbb, 0xb5, 0xc1, 0x02, 0x7f, 0x57, 0x0f, 0xaf, 0xb2, 0xc6,
+	0xd2, 0x7c, 0x8b, 0xd4, 0x73, 0x77, 0x02, 0x4d, 0xd6, 0xf0, 0x42, 0xdf, 0x75, 0xe5, 0x92, 0xee,
+	0xc4, 0x9e, 0x2d, 0x98, 0x1e, 0xb4, 0x0b, 0x26, 0xbc, 0xfa, 0x16, 0x0b, 0xe3, 0xa1, 0x2d, 0x98,
+	0xe2, 0x40, 0xfb, 0x11, 0x9d, 0xb8, 0x32, 0x4a, 0x61, 0xf0, 0x60, 0xff, 0xb0, 0x83, 0xbe, 0x1c,
+	0x76, 0xd0, 0xb7, 0xc3, 0x0e, 0xfa, 0x7c, 0xd4, 0x41, 0xfb, 0x47, 0x1d, 0xf4, 0xfc, 0xda, 0xf1,
+	0x15, 0x8b, 0x3c, 0xed, 0xa9, 0xfc, 0x9c, 0x3a, 0xfc, 0x67, 0xee, 0xfc, 0x08, 0x00, 0x00, 0xff,
+	0xff, 0xf8, 0x92, 0x62, 0xb5, 0xce, 0x06, 0x00, 0x00,
 }
diff --git a/txs/payload/permission_tx.go b/txs/payload/perms_tx.go
similarity index 53%
rename from txs/payload/permission_tx.go
rename to txs/payload/perms_tx.go
index d22984f9..5dbff87e 100644
--- a/txs/payload/permission_tx.go
+++ b/txs/payload/perms_tx.go
@@ -8,7 +8,7 @@ import (
 	"github.com/hyperledger/burrow/permission"
 )
 
-func NewPermissionsTx(st state.AccountGetter, from crypto.PublicKey, args permission.PermArgs) (*PermissionsTx, error) {
+func NewPermsTx(st state.AccountGetter, from crypto.PublicKey, args permission.PermArgs) (*PermsTx, error) {
 	addr := from.Address()
 	acc, err := st.GetAccount(addr)
 	if err != nil {
@@ -19,30 +19,36 @@ func NewPermissionsTx(st state.AccountGetter, from crypto.PublicKey, args permis
 	}
 
 	sequence := acc.Sequence() + 1
-	return NewPermissionsTxWithSequence(from, args, sequence), nil
+	return NewPermsTxWithSequence(from, args, sequence), nil
 }
 
-func NewPermissionsTxWithSequence(from crypto.PublicKey, args permission.PermArgs, sequence uint64) *PermissionsTx {
+func NewPermsTxWithSequence(from crypto.PublicKey, args permission.PermArgs, sequence uint64) *PermsTx {
 	input := &TxInput{
 		Address:  from.Address(),
 		Amount:   1, // NOTE: amounts can't be 0 ...
 		Sequence: sequence,
 	}
 
-	return &PermissionsTx{
+	return &PermsTx{
 		Input:    input,
 		PermArgs: args,
 	}
 }
 
-func (tx *PermissionsTx) Type() Type {
+func (tx *PermsTx) Type() Type {
 	return TypePermissions
 }
 
-func (tx *PermissionsTx) GetInputs() []*TxInput {
+func (tx *PermsTx) GetInputs() []*TxInput {
 	return []*TxInput{tx.Input}
 }
 
-func (tx *PermissionsTx) String() string {
-	return fmt.Sprintf("PermissionsTx{%v -> %v}", tx.Input, tx.PermArgs)
+func (tx *PermsTx) String() string {
+	return fmt.Sprintf("PermsTx{%v -> %v}", tx.Input, tx.PermArgs)
+}
+
+func (tx *PermsTx) Any() *Any {
+	return &Any{
+		PermsTx: tx,
+	}
 }
diff --git a/txs/payload/send_tx.go b/txs/payload/send_tx.go
index f83fcf95..c67babef 100644
--- a/txs/payload/send_tx.go
+++ b/txs/payload/send_tx.go
@@ -55,3 +55,9 @@ func (tx *SendTx) AddOutput(addr crypto.Address, amt uint64) error {
 	})
 	return nil
 }
+
+func (tx *SendTx) Any() *Any {
+	return &Any{
+		SendTx: tx,
+	}
+}
diff --git a/txs/payload/unbond_tx.go b/txs/payload/unbond_tx.go
index c6fe036f..c295cfad 100644
--- a/txs/payload/unbond_tx.go
+++ b/txs/payload/unbond_tx.go
@@ -24,3 +24,9 @@ func (tx *UnbondTx) GetInputs() []*TxInput {
 func (tx *UnbondTx) String() string {
 	return fmt.Sprintf("UnbondTx{%v -> %s,%v}", tx.Input, tx.Address, tx.Height)
 }
+
+func (tx *UnbondTx) Any() *Any {
+	return &Any{
+		UnbondTx: tx,
+	}
+}
diff --git a/txs/tx.go b/txs/tx.go
index ee773c3c..45b15ca8 100644
--- a/txs/tx.go
+++ b/txs/tx.go
@@ -103,7 +103,7 @@ func (tx *Tx) UnmarshalJSON(data []byte) error {
 	}
 	tx.ChainID = w.ChainID
 	// Now we know the Type we can deserialise the Payload
-	tx.Payload = payload.New(w.Type)
+	tx.Payload, err = payload.New(w.Type)
 	return json.Unmarshal(w.Payload, tx.Payload)
 }
 
diff --git a/txs/tx_test.go b/txs/tx_test.go
index 4716bc28..b3d0d4a4 100644
--- a/txs/tx_test.go
+++ b/txs/tx_test.go
@@ -153,7 +153,7 @@ func TestUnbondTxSignable(t *testing.T) {
 }
 
 func TestPermissionsTxSignable(t *testing.T) {
-	permsTx := &payload.PermissionsTx{
+	permsTx := &payload.PermsTx{
 		Input: &payload.TxInput{
 			Address:  makePrivateAccount("input1").Address(),
 			Amount:   12345,
@@ -191,7 +191,7 @@ func TestTxWrapper_MarshalJSON(t *testing.T) {
 func TestNewPermissionsTxWithSequence(t *testing.T) {
 	privateAccount := makePrivateAccount("shhhhh")
 	args := permission.SetBaseArgs(privateAccount.PublicKey().Address(), permission.HasRole, true)
-	permTx := payload.NewPermissionsTxWithSequence(privateAccount.PublicKey(), args, 1)
+	permTx := payload.NewPermsTxWithSequence(privateAccount.PublicKey(), args, 1)
 	testTxMarshalJSON(t, permTx)
 	testTxSignVerify(t, permTx)
 }
diff --git a/util/logging/cmd/main.go b/util/logging/cmd/main.go
index cc6960b6..d0b8acda 100644
--- a/util/logging/cmd/main.go
+++ b/util/logging/cmd/main.go
@@ -17,7 +17,7 @@ package main
 import (
 	"fmt"
 
-	. "github.com/hyperledger/burrow/logging/config"
+	. "github.com/hyperledger/burrow/logging/logconfig"
 )
 
 // Dump an example logging configuration
-- 
GitLab