diff --git a/Makefile b/Makefile
index 86ad8624ab0e673ec4a6f93842c7003822c31a36..ffa4a8d410f68e630c6c842a1cde5bcb5053d88f 100644
--- a/Makefile
+++ b/Makefile
@@ -10,18 +10,18 @@ SHELL := /bin/bash
 REPO := $(shell pwd)
 GOFILES_NOVENDOR := $(shell go list -f "{{.Dir}}" ./...)
 PACKAGES_NOVENDOR := $(shell go list ./...)
-LDFLAGS :=
 # Bosmarmot integration testing
 BOSMARMOT_PROJECT := github.com/monax/bosmarmot
 BOSMARMOT_GOPATH := ${REPO}/.gopath_bos
 BOSMARMOT_CHECKOUT := ${BOSMARMOT_GOPATH}/src/${BOSMARMOT_PROJECT}
 
 # Protobuf generated go files
-PROTO_FILES = $(shell find . -path ./vendor -prune -o -type f -name '*.proto')
+PROTO_FILES = $(shell find . -path ./vendor -prune -o -type f -name '*.proto' -print)
 PROTO_GO_FILES = $(patsubst %.proto, %.pb.go, $(PROTO_FILES))
+PROTO_GO_FILES_REAL = $(shell find . -path ./vendor -prune -o -type f -name '*.pb.go' -print)
 
 # Our own Go files containing the compiled bytecode of solidity files as a constant
-SOLIDITY_FILES = $(shell find . -path ./vendor -prune -o -type f -name '*.sol')
+SOLIDITY_FILES = $(shell find . -path ./vendor -prune -o -type f -name '*.sol' -print)
 SOLIDITY_GO_FILES = $(patsubst %.sol, %.sol.go, $(SOLIDITY_FILES))
 
 ### Formatting, linting and vetting
@@ -71,18 +71,20 @@ megacheck:
 # Protobuffing
 .PHONY: protobuf_deps
 protobuf_deps:
-	@go get -u github.com/golang/protobuf/protoc-gen-go
+	@go get -u github.com/gogo/protobuf/protoc-gen-gogo
+#	@go get -u github.com/golang/protobuf/protoc-gen-go
 
-# Implicit compile rule for GRPC/proto files
+# Implicit compile rule for GRPC/proto files (note since pb.go files no longer generated
+# in same directory as proto file this just regenerates everything
 %.pb.go: %.proto
-	protoc -I ${GOPATH}/src ${REPO}/$< --go_out=plugins=grpc:${GOPATH}/src
+	protoc -I vendor -I protobuf $< --gogo_out=plugins=grpc:${GOPATH}/src
 
 .PHONY: protobuf
 protobuf: $(PROTO_GO_FILES)
 
 .PHONY: clean_protobuf
 clean_protobuf:
-	@rm -f $(PROTO_GO_FILES)
+	@rm -f $(PROTO_GO_FILES_REAL)
 
 ### Dependency management for github.com/hyperledger/burrow
 # erase vendor wipes the full vendor directory
@@ -117,11 +119,11 @@ commit_hash:
 
 # build all targets in github.com/hyperledger/burrow
 .PHONY: build
-build:	check build_db build_client
+build:	check build_db
 
 # build all targets in github.com/hyperledger/burrow with checks for race conditions
 .PHONY: build_race
-build_race:	check build_race_db build_race_client
+build_race:	check build_race_db
 
 # build burrow
 .PHONY: build_db
@@ -134,23 +136,11 @@ build_db: commit_hash
 install_db: build_db
 	cp ${REPO}/bin/burrow ${GOPATH}/bin/burrow
 
-# build burrow-client
-.PHONY: build_client
-build_client: commit_hash
-	go build -ldflags "-extldflags '-static' \
-	-X github.com/hyperledger/burrow/project.commit=$(shell cat commit_hash.txt)" \
-	-o ${REPO}/bin/burrow-client ./client/cmd/burrow-client
-
 # build burrow with checks for race conditions
 .PHONY: build_race_db
 build_race_db:
 	go build -race -o ${REPO}/bin/burrow ./cmd/burrow
 
-# build burrow-client with checks for race conditions
-.PHONY: build_race_client
-build_race_client:
-	go build -race -o ${REPO}/bin/burrow-client ./client/cmd/burrow-client
-
 # Get the Bosmarmot code
 .PHONY: bos
 bos: ./scripts/deps/bos.sh
@@ -185,15 +175,13 @@ test: check
 test_keys: build_db
 	burrow_bin="${REPO}/bin/burrow" keys/test.sh
 
-rpc/test/strange_loop.go: rpc/test/strange_loop.sol
+rpc/test/strange_loop.go: integration/rpctest
 	@rpc/test/strange_loop.sh
 
+# Go will attempt to run separate packages in parallel
 .PHONY: test_integration
 test_integration: test_keys
-	@go test -tags integration ./rpc/rpcevents/integration
-	@go test -tags integration ./rpc/rpctransactor/integration
-	@go test -tags integration ./rpc/v0/integration
-	@go test -tags integration ./rpc/tm/integration
+	@go test -v -tags integration ./integration/...
 
 # Run integration test from bosmarmot (separated from other integration tests so we can
 # make exception when this test fails when we make a breaking change in Burrow)
diff --git a/protobuf/acm.proto b/protobuf/acm.proto
new file mode 100644
index 0000000000000000000000000000000000000000..8a52a277de260e10ea9fe44d7f271db2b8d88561
--- /dev/null
+++ b/protobuf/acm.proto
@@ -0,0 +1,31 @@
+syntax = 'proto3';
+
+package acm;
+
+option go_package = "github.com/hyperledger/burrow/acm";
+
+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 {
+    option (gogoproto.goproto_stringer) = false;
+    bytes Address = 1 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.nullable) = false];
+    crypto.PublicKey PublicKey = 2 [(gogoproto.nullable) = false];
+    uint64 Sequence = 3;
+    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/crypto.proto b/protobuf/crypto.proto
new file mode 100644
index 0000000000000000000000000000000000000000..425236f4c87154b12bd7d762edde8ab0fb2396c8
--- /dev/null
+++ b/protobuf/crypto.proto
@@ -0,0 +1,29 @@
+syntax = 'proto3';
+
+package crypto;
+
+option go_package = "github.com/hyperledger/burrow/crypto";
+
+import "github.com/gogo/protobuf/gogoproto/gogo.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;
+
+// PublicKey
+message PublicKey {
+    option (gogoproto.goproto_stringer) = false;
+    uint32 CurveType = 1 [(gogoproto.casttype) = "CurveType"];
+    bytes PublicKey = 2;
+}
+
+message PrivateKey {
+    option (gogoproto.goproto_stringer) = false;
+    option (gogoproto.goproto_getters) = false;
+    uint32 CurveType = 1 [(gogoproto.casttype) = "CurveType"];
+    // Note may need initialisation
+    bytes PublicKey = 2;
+    bytes PrivateKey = 3;
+}
diff --git a/protobuf/errors.proto b/protobuf/errors.proto
new file mode 100644
index 0000000000000000000000000000000000000000..6f81e457bfd52e7a20c841c96e09c4bc0d79c370
--- /dev/null
+++ b/protobuf/errors.proto
@@ -0,0 +1,24 @@
+syntax = "proto3";
+
+package errors;
+
+option go_package = "github.com/hyperledger/burrow/execution/errors";
+
+import "github.com/gogo/protobuf/gogoproto/gogo.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 Exception {
+    option (gogoproto.goproto_stringer) = false;
+    uint32 Code = 1 [(gogoproto.casttype) = "Code"];
+    string Exception = 2;
+}
diff --git a/protobuf/exec.proto b/protobuf/exec.proto
new file mode 100644
index 0000000000000000000000000000000000000000..6eb935117ab1d814db1aadc9bfa348aaf7774de7
--- /dev/null
+++ b/protobuf/exec.proto
@@ -0,0 +1,149 @@
+syntax = 'proto3';
+
+package exec;
+
+option go_package = "github.com/hyperledger/burrow/execution/exec";
+
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+import "github.com/tendermint/abci/types/types.proto";
+
+import "errors.proto";
+import "names.proto";
+import "txs.proto";
+import "permission.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 BlockExecution {
+    // The height of this block
+    uint64 Height = 1;
+    // TODO: reintroduce this when upstream merges: https://github.com/tendermint/tendermint/pull/1987
+//    types.Header BlockHeader = 2;
+    BlockHeader BlockHeader = 2;
+    repeated TxExecution TxExecutions = 3;
+}
+
+message BlockHeader {
+    string JSON = 1;
+    int32 NumTxs = 2;
+}
+
+message TxExecution {
+    option (gogoproto.sizer) = true;
+    option (gogoproto.marshaler) = true;
+    option (gogoproto.unmarshaler) = true;
+    // Transaction type
+    uint32 TxType = 2 [(gogoproto.casttype) = "github.com/hyperledger/burrow/txs/payload.Type"];
+    // The hash of the transaction that caused this event to be generated
+    bytes TxHash = 3 [(gogoproto.customtype) = "github.com/hyperledger/burrow/binary.HexBytes", (gogoproto.nullable) = false];
+    // The block height at which this Tx was included
+    uint64 Height = 4;
+    // The index of this transaction within the block
+    uint64 Index = 5;
+    // Signed Tx that triggered this execution
+    txs.Envelope Envelope = 6 [(gogoproto.customtype) = "github.com/hyperledger/burrow/txs.Envelope"];
+    // Execution events
+    repeated Event Events = 7;
+    // The execution results
+    Result Result = 8;
+    // The transaction receipt
+    txs.Receipt Receipt = 9;
+    // If execution was an exception
+    errors.Exception Exception = 10;
+}
+
+message Header {
+    option (gogoproto.goproto_stringer) = false;
+    option (gogoproto.sizer) = true;
+    option (gogoproto.marshaler) = true;
+    option (gogoproto.unmarshaler) = true;
+    // Transaction type
+    uint32 TxType = 1 [(gogoproto.casttype) = "github.com/hyperledger/burrow/txs/payload.Type"];
+    // The hash of the transaction that caused this event to be generated
+    bytes TxHash = 2 [(gogoproto.customtype) = "github.com/hyperledger/burrow/binary.HexBytes", (gogoproto.nullable) = false];
+    // The type of event
+    uint32 EventType = 3 [(gogoproto.casttype) = "EventType"];
+    // EventID published with event
+    string EventID = 4;
+    // The block height at which this event was emitted
+    uint64 Height = 5;
+    // The index of this event relative to other events generated by the same transaction
+    uint64 Index = 6;
+    // If event is exception
+    errors.Exception Exception = 7;
+}
+
+message Event {
+    option (gogoproto.sizer) = true;
+    option (gogoproto.marshaler) = true;
+    option (gogoproto.unmarshaler) = true;
+    option (gogoproto.goproto_stringer) = false;
+    Header Header = 1;
+    InputEvent Input = 2;
+    OutputEvent Output = 3;
+    CallEvent Call = 4;
+    LogEvent Log = 5;
+}
+
+// Could structure this further if needed - sum type of various results relevant to different transaction types
+message Result {
+    option (gogoproto.sizer) = true;
+    option (gogoproto.marshaler) = true;
+    option (gogoproto.unmarshaler) = true;
+    // EVM execution return
+    bytes Return = 1;
+    // Gas used in computation
+    uint64 GasUsed = 2;
+    // Name entry created
+    names.Entry NameEntry = 3;
+    // Permission update performed
+    permission.PermArgs PermArgs = 4;
+}
+
+message LogEvent {
+    option (gogoproto.sizer) = true;
+    option (gogoproto.marshaler) = true;
+    option (gogoproto.unmarshaler) = true;
+    bytes Address = 1 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.nullable) = false];
+    bytes Data = 2 [(gogoproto.customtype) = "github.com/hyperledger/burrow/binary.HexBytes", (gogoproto.nullable) = false];
+    repeated bytes Topics = 3 [(gogoproto.customtype) = "github.com/hyperledger/burrow/binary.Word256", (gogoproto.nullable) = false];
+}
+
+message CallEvent {
+    option (gogoproto.sizer) = true;
+    option (gogoproto.marshaler) = true;
+    option (gogoproto.unmarshaler) = true;
+    CallData CallData = 1;
+    bytes Origin = 2 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.nullable) = false];
+    uint64 StackDepth = 3;
+    bytes Return = 4 [(gogoproto.customtype) = "github.com/hyperledger/burrow/binary.HexBytes", (gogoproto.nullable) = false];
+}
+
+message InputEvent {
+    option (gogoproto.sizer) = true;
+    option (gogoproto.marshaler) = true;
+    option (gogoproto.unmarshaler) = true;
+    bytes Address = 1 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.nullable) = false];
+}
+
+message OutputEvent {
+    option (gogoproto.sizer) = true;
+    option (gogoproto.marshaler) = true;
+    option (gogoproto.unmarshaler) = true;
+    bytes Address = 1 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.nullable) = false];
+}
+
+message CallData {
+    option (gogoproto.sizer) = true;
+    option (gogoproto.marshaler) = true;
+    option (gogoproto.unmarshaler) = true;
+    bytes Caller = 1 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.nullable) = false];
+    bytes Callee = 2 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.nullable) = false];
+    bytes Data = 3 [(gogoproto.customtype) = "github.com/hyperledger/burrow/binary.HexBytes", (gogoproto.nullable) = false];
+    uint64 Value = 4;
+    uint64 Gas = 5;
+}
diff --git a/protobuf/keys.proto b/protobuf/keys.proto
new file mode 100644
index 0000000000000000000000000000000000000000..caf39d37d5b0531f37be6c0da234cccf2617929c
--- /dev/null
+++ b/protobuf/keys.proto
@@ -0,0 +1,141 @@
+syntax = "proto3";
+
+option go_package = "github.com/hyperledger/burrow/keys";
+
+package keys;
+
+import "github.com/gogo/protobuf/gogoproto/gogo.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;
+
+service Keys {
+    rpc GenerateKey(GenRequest) returns (GenResponse);
+    rpc PublicKey(PubRequest) returns (PubResponse);
+    rpc Sign(SignRequest) returns (SignResponse);
+    rpc Verify(VerifyRequest) returns (VerifyResponse);
+    rpc Import(ImportRequest) returns (ImportResponse);
+    rpc ImportJSON(ImportJSONRequest) returns (ImportResponse);
+    rpc Export(ExportRequest) returns (ExportResponse);
+    rpc Hash(HashRequest) returns (HashResponse);
+    rpc RemoveName(RemoveNameRequest) returns (RemoveNameResponse);
+    rpc List(ListRequest) returns (ListResponse);
+    rpc AddName(AddNameRequest) returns (AddNameResponse);
+}
+
+// Some empty types we may define later
+
+message ListRequest {
+
+}
+
+message VerifyResponse {
+
+}
+
+message RemoveNameResponse {
+
+}
+
+message AddNameResponse {
+
+}
+
+message RemoveNameRequest {
+    string KeyName = 1;
+}
+
+
+message GenRequest {
+    string Passphrase = 1;
+    string CurveType = 2;
+    string KeyName = 3;
+}
+
+message GenResponse {
+    string Address = 1;
+}
+
+message PubRequest {
+    string Address = 1;
+    string Name = 2;
+} 
+
+message PubResponse {
+    bytes PublicKey = 1;
+    string CurveType = 2;
+}
+
+message ImportJSONRequest {
+    string Passphrase = 1;
+    string JSON = 2;
+}
+
+message ImportResponse {
+    string Address = 1;
+}
+
+message ImportRequest {
+    string Passphrase = 1;
+    string Name = 2;
+    string CurveType = 3;
+    bytes KeyBytes = 4;
+}
+
+message ExportRequest {
+    string Passphrase = 1;
+    string Name = 2;
+    string Address = 3;
+}
+
+message ExportResponse {
+    bytes Publickey = 1;
+    bytes Privatekey = 2;
+    bytes Address = 3;
+    string CurveType = 4;
+}
+
+message SignRequest {
+    string Passphrase = 1;
+    string Address = 2;
+    string Name = 3;
+    bytes Message = 4;
+}
+
+message SignResponse {
+    bytes Signature = 1;
+    string CurveType = 2;
+}
+
+message VerifyRequest {
+    string CurveType = 1;
+    bytes PublicKey = 2;
+    bytes Message = 3;
+    bytes Signature = 4;
+}
+
+message HashRequest {
+    string Hashtype = 1;
+    bytes Message = 2;
+}
+
+message HashResponse {
+    string Hash = 1;
+}
+
+message KeyID {
+    string Address = 1;
+    string KeyName = 2;
+}
+
+message ListResponse {
+    repeated KeyID key = 1;
+}
+
+message AddNameRequest {
+    string Keyname = 1;
+    string Address = 2;
+}
diff --git a/protobuf/names.proto b/protobuf/names.proto
new file mode 100644
index 0000000000000000000000000000000000000000..0be792b2d50b3d2f5a4cff9830684ed9a798b9d0
--- /dev/null
+++ b/protobuf/names.proto
@@ -0,0 +1,33 @@
+syntax = 'proto3';
+
+package names;
+
+option go_package = "github.com/hyperledger/burrow/execution/names";
+
+import "github.com/gogo/protobuf/gogoproto/gogo.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;
+
+// NameReg provides a global key value store based on Name, Data pairs that are subject to expiry and ownership by an
+// account.
+message Entry {
+    option (gogoproto.goproto_stringer) = false;
+    // registered name for the entry
+    string Name = 1;
+    // address that created the entry
+    bytes Owner = 2 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.nullable) = false];
+    // data to store under this name
+    string Data = 3;
+    // block at which this entry expires
+    uint64 Expires = 4;
+}
+
diff --git a/protobuf/payload.proto b/protobuf/payload.proto
new file mode 100644
index 0000000000000000000000000000000000000000..1e75fdf40072f6f150d40c022e77e26d64492a1a
--- /dev/null
+++ b/protobuf/payload.proto
@@ -0,0 +1,123 @@
+syntax = 'proto3';
+
+option go_package = "github.com/hyperledger/burrow/txs/payload";
+
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+import "permission.proto";
+import "spec.proto";
+
+package payload;
+
+// 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 AnyPayload {
+    CallTx CallTx = 1;
+    SendTx SendTx = 2;
+    NameTx NameTx = 3;
+    PermissionsTx PermissionsTx = 4;
+    GovernanceTx GovernanceTx = 5;
+}
+
+// An input to a transaction that may carry an Amount as a charge and whose sequence number must be one greater than
+// that associated with the account at Address at the time of being received
+message TxInput {
+    option (gogoproto.goproto_stringer) = false;
+    // The address from which this input flows
+    bytes Address = 1 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.nullable) = false];
+    // The amount of native token to transfer from the input address
+    uint64 Amount = 2;
+    // The sequence number that this transaction will induce (i.e. one greater than the input account's current sequence)
+    uint64 Sequence = 3;
+}
+
+// An output from a transaction that may carry an amount as a charge
+message TxOutput {
+    option (gogoproto.goproto_stringer) = false;
+    // The address to which this output flows
+    bytes Address = 1 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.nullable) = false];
+    // The amount of native token to transfer to the output address
+    uint64 Amount = 2;
+}
+
+// A instruction to run smart contract code in the EVM
+message CallTx {
+    option (gogoproto.goproto_stringer) = false;
+    // The caller's input
+    TxInput Input = 1;
+    // The contract address to call or nil if we are creating a contract
+    bytes Address = 2 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address"];
+    // The upper bound on the amount of gas (and therefore EVM execution steps) this CallTx may generate
+    uint64 GasLimit = 3;
+    // Fee to offer validators for processing transaction
+    uint64 Fee = 4;
+    // EVM bytecode payload
+    bytes Data = 5 [(gogoproto.customtype) = "github.com/hyperledger/burrow/binary.HexBytes", (gogoproto.nullable) = false];
+
+}
+
+// A payment between two sets of parties
+message SendTx {
+    option (gogoproto.goproto_stringer) = false;
+    option (gogoproto.goproto_getters) = false;
+    // The payers
+    repeated TxInput Inputs = 1;
+    // The payees
+    repeated TxOutput Outputs = 2;
+}
+
+// An update to the on-chain permissions
+message PermissionsTx {
+    option (gogoproto.goproto_stringer) = false;
+    // The permission moderator
+    TxInput Input = 1;
+    // The modified permissions
+    permission.PermArgs PermArgs = 2 [(gogoproto.nullable) = false];
+}
+
+// A request to claim a globally unique name across the entire chain with some optional data storage leased for a fee
+message NameTx {
+    option (gogoproto.goproto_stringer) = false;
+    // The name updater
+    TxInput Input = 1;
+    // The name to update or create
+    string Name = 2;
+    // The data to store against the name
+    string Data = 3;
+    // The fee to provide that will determine the lenght of the name lease
+    uint64 Fee = 4;
+}
+
+message BondTx {
+    option (gogoproto.goproto_stringer) = false;
+    option (gogoproto.goproto_getters) = false;
+
+    repeated TxInput Inputs = 1;
+    repeated TxOutput UnbondTo = 2;
+}
+
+message UnbondTx {
+    option (gogoproto.goproto_stringer) = false;
+    option (gogoproto.goproto_getters) = false;
+
+    TxInput Input = 1;
+    bytes Address = 2 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.nullable) = false];
+    uint64 Height = 3;
+}
+
+message GovernanceTx {
+    option (gogoproto.goproto_stringer) = false;
+    option (gogoproto.goproto_getters) = false;
+
+    repeated TxInput Inputs = 1;
+    repeated spec.TemplateAccount AccountUpdates = 2 [(gogoproto.nullable) = true];
+}
diff --git a/protobuf/permission.proto b/protobuf/permission.proto
new file mode 100644
index 0000000000000000000000000000000000000000..d7ba52af5dd3ace0ffcb79596c26a819a263ceb6
--- /dev/null
+++ b/protobuf/permission.proto
@@ -0,0 +1,39 @@
+syntax = 'proto2';
+
+package permission;
+
+option go_package = "github.com/hyperledger/burrow/permission";
+
+import "github.com/gogo/protobuf/gogoproto/gogo.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 AccountPermissions {
+    optional BasePermissions Base = 1 [(gogoproto.nullable) = false];
+    repeated string Roles = 2;
+}
+
+message BasePermissions {
+    option (gogoproto.goproto_stringer) = false;
+    optional uint64 Perms = 1 [(gogoproto.casttype) = "PermFlag", (gogoproto.nullable) = false];
+    optional uint64 SetBit = 2 [(gogoproto.casttype) = "PermFlag", (gogoproto.nullable) = false];
+}
+
+message PermArgs {
+    option (gogoproto.goproto_unrecognized) = false;
+    option (gogoproto.goproto_stringer) = false;
+    optional uint64 PermFlag = 1 [(gogoproto.casttype) = "PermFlag", (gogoproto.nullable) = false];
+    optional bytes Address = 2 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address"];
+    optional uint64 Permission = 3 [(gogoproto.casttype) = "PermFlag"];
+    optional string Role = 4;
+    optional bool Value = 5;
+}
diff --git a/protobuf/rpcevents.proto b/protobuf/rpcevents.proto
new file mode 100644
index 0000000000000000000000000000000000000000..39d824196011fade5e146dc5474eafe2aff56d7e
--- /dev/null
+++ b/protobuf/rpcevents.proto
@@ -0,0 +1,128 @@
+syntax = 'proto3';
+
+option go_package = "github.com/hyperledger/burrow/rpc/rpcevents";
+
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+import "exec.proto";
+
+package rpcevents;
+
+// 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;
+
+//--------------------------------------------------
+// Execution events
+service ExecutionEvents {
+    // Get Blockexecution at particular height
+    rpc GetBlock (GetBlockRequest) returns (exec.BlockExecution);
+    // Get BlockExecutions for a range of blocks
+    rpc GetBlocks (BlocksRequest) returns (stream exec.BlockExecution);
+    // Get a particular TxExecution
+    rpc GetTx (GetTxRequest) returns (exec.TxExecution);
+    // Get TxExecutions for a range of block
+    rpc GetTxs (BlocksRequest) returns (stream GetTxsResponse);
+    // GetEvents provides events streaming one block at a time - that is all events emitted in a particular block
+    // are guaranteed to be delivered in each GetEventsResponse
+    rpc GetEvents (BlocksRequest) returns (stream GetEventsResponse);
+}
+
+message GetBlockRequest {
+    // Height of block required
+    uint64 Height = 1;
+    // Whether to wait for the block to become available
+    bool Wait = 2;
+}
+
+message GetTxRequest {
+    // Height of block required
+    bytes TxHash = 1 [(gogoproto.customtype) = "github.com/hyperledger/burrow/binary.HexBytes", (gogoproto.nullable) = false];
+    // Whether to wait for the block to become available
+    bool Wait = 2;
+}
+
+message BlocksRequest {
+    BlockRange BlockRange = 1;
+    // Specify a query on which to match the tags of events.
+    // Tag        | Match type | Values
+    // -----------------------------------------
+    //   All events
+    // -----------------------------------------
+    // TxType       | String     | "UnknownTx", "SendTx", "CallTx", "NameTx", "BondTx", "UnbondTx", "PermissionsTx", "GovernanceTx"
+    // TxHash       | String     | bytes
+    // EventType    | String     | "CallEvent", "LogEvent", "AccountInputEvent", "AccountOutputEvent"
+    // EventID      | String     | string
+    // Height       | Integer    | uint64
+    // Index        | Integer    | uint64
+    // MessageType  | String     | Go type name
+    // -----------------------------------------
+    //   Log event
+    // -----------------------------------------
+    // Address      | String     | Address (hex)
+    // Log<0-4>     | String     | Word256 (hex)
+    // Log<0-4>Text | String     | string (trimmed)
+    // -----------------------------------------
+    //   Call event
+    // -----------------------------------------
+    // Origin       | String     | Address (hex)
+    // Callee       | String     | Address (hex)
+    // Caller       | String     | Address (hex)
+    // Value        | Integer    | uint64
+    // Gas          | Integer    | uint64
+    // StackDepth   | Integer    | uint64
+    // Exception    | String     | string
+    // -----------------------------------------
+    //   Tx event (input/output)
+    // -----------------------------------------
+    // Exception  | String     | string
+    //
+    // For example:
+    // EventType = 'LogEvent' AND EventID CONTAINS 'bar' AND TxHash = '020304' AND Height >= 34 AND Index < 3 AND Address = 'DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF'
+    string Query = 2;
+}
+
+message GetEventsResponse {
+    uint64 Height = 1;
+    repeated exec.Event Events = 2;
+}
+
+message GetTxsResponse {
+    uint64 Height = 1;
+    repeated exec.TxExecution TxExecutions = 2;
+}
+
+message Bound {
+    BoundType Type = 1;
+    uint64 Index = 2;
+    enum BoundType {
+        // Index is absolute index of an item
+        ABSOLUTE = 0;
+        // Index is an offset relative to last item
+        RELATIVE = 1;
+        // The first block
+        FIRST = 2;
+        // Ignore provided index and evaluate to latest index
+        LATEST = 3;
+        // Ignore provided index and stream new objects as they are generated
+        STREAM = 4;
+    }
+}
+
+// An inclusive range of blocks to include in output
+message BlockRange {
+    // Bounds can be set to:
+    // absolute: block height
+    // relative: block height counting back from latest
+    // latest: latest block when call is processed
+    // stream: for End keep sending new blocks, for start same as latest
+    Bound Start = 1;
+    Bound End = 2;
+}
+
diff --git a/protobuf/rpcquery.proto b/protobuf/rpcquery.proto
new file mode 100644
index 0000000000000000000000000000000000000000..bbb5122559808e119f59aa259996752c69dc6cb5
--- /dev/null
+++ b/protobuf/rpcquery.proto
@@ -0,0 +1,40 @@
+syntax = 'proto3';
+
+package rpcquery;
+
+option go_package = "github.com/hyperledger/burrow/rpc/rpcquery";
+
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+import "names.proto";
+import "acm.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;
+
+service Query {
+    rpc GetAccount (GetAccountParam) returns (acm.ConcreteAccount);
+    rpc ListAccounts (ListAccountsParam) returns (stream acm.ConcreteAccount);
+    rpc GetName (GetNameParam) returns (names.Entry);
+    rpc ListNames (ListNamesParam) returns (stream names.Entry);
+}
+
+message GetAccountParam {
+    bytes Address = 1 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.nullable) = false];
+}
+
+message ListAccountsParam {
+    string Query = 1;
+}
+
+message GetNameParam {
+    string Name = 1;
+}
+
+message ListNamesParam {
+    string Query = 1;
+}
+
diff --git a/protobuf/rpctransact.proto b/protobuf/rpctransact.proto
new file mode 100644
index 0000000000000000000000000000000000000000..b2753a171b9a9980935671964bc7d0200b16fa4c
--- /dev/null
+++ b/protobuf/rpctransact.proto
@@ -0,0 +1,80 @@
+syntax = 'proto3';
+
+package rpctransact;
+
+option go_package = "github.com/hyperledger/burrow/rpc/rpctransact";
+
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+import "exec.proto";
+import "payload.proto";
+import "txs.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;
+
+// Transaction Service Definition
+service Transact {
+    // Broadcast a transaction to the mempool - if the transaction is not signed signing will be attempted server-side
+    // and wait for it to be included in block
+    rpc BroadcastTxSync (TxEnvelopeParam) returns (exec.TxExecution);
+    // Broadcast a transaction to the mempool - if the transaction is not signed signing will be attempted server-side
+    rpc BroadcastTxAsync (TxEnvelopeParam) returns (txs.Receipt);
+
+    // 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);
+
+    // 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);
+    // Formulate and sign a CallTx transaction signed server-side
+    rpc CallTxAsync (payload.CallTx) returns (txs.Receipt);
+    // Perform a 'simulated' call of a contract against the current committed EVM state without any changes been saved
+    // and wait for the transaction to be included in a block
+    rpc CallTxSim (payload.CallTx) returns (exec.TxExecution);
+    // Perform a 'simulated' execution of provided code against the current committed EVM state without any changes been saved
+    rpc CallCodeSim (CallCodeParam) returns (exec.TxExecution);
+
+    // Formulate a SendTx transaction signed server-side and wait for it to be included in a block, retrieving response
+    rpc SendTxSync (payload.SendTx) returns (exec.TxExecution);
+    // Formulate and  SendTx transaction signed server-side
+    rpc SendTxAsync (payload.SendTx) returns (txs.Receipt);
+
+    // Formualte a NameTx signed server-side and wait for it to be included in a block returning the registered name
+    rpc NameTxSync (payload.NameTx) returns (exec.TxExecution);
+    // Formulate a NameTx signed server-side
+    rpc NameTxAsync (payload.NameTx) returns (txs.Receipt);
+}
+
+message CallCodeParam {
+    bytes FromAddress = 1 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.nullable) = false];
+    bytes Code = 2;
+    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"];
+}
+
+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;
+}
+
diff --git a/protobuf/spec.proto b/protobuf/spec.proto
new file mode 100644
index 0000000000000000000000000000000000000000..7f0c6abec74ff569deef8370c0bf7ded2ed7825d
--- /dev/null
+++ b/protobuf/spec.proto
@@ -0,0 +1,35 @@
+// Needed to proto2 rather than proto3 to get pointer field for PermArg
+syntax = 'proto2';
+
+option go_package = "github.com/hyperledger/burrow/genesis/spec";
+
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+import "crypto.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\""];
+}
+
diff --git a/protobuf/txs.proto b/protobuf/txs.proto
new file mode 100644
index 0000000000000000000000000000000000000000..b7048d4a7fb71111b593f1891be04efe02f5b466
--- /dev/null
+++ b/protobuf/txs.proto
@@ -0,0 +1,47 @@
+syntax = 'proto3';
+
+option go_package = "github.com/hyperledger/burrow/txs";
+
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+import "crypto.proto";
+
+package txs;
+
+// 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;
+
+// An envelope contains both the signable Tx and the signatures for each input (in signatories)
+message Envelope {
+    option (gogoproto.goproto_stringer) = false;
+    repeated Signatory Signatories = 1 [(gogoproto.nullable) = false];
+    // Canonical bytes of the Tx ready to be signed
+    bytes Tx = 2 [(gogoproto.customtype) = "Tx"];
+}
+
+// Signatory contains signature and one or both of Address and PublicKey to identify the signer
+message Signatory {
+    bytes Address = 1 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address"];
+    crypto.PublicKey PublicKey = 2;
+    bytes Signature = 3 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Signature", (gogoproto.nullable) = false];
+}
+
+// BroadcastTx or Transaction receipt
+message Receipt {
+    // Transaction type
+    uint32 TxType = 1[(gogoproto.casttype) = "github.com/hyperledger/burrow/txs/payload.Type"];
+    // The hash of the transaction that caused this event to be generated
+    bytes TxHash = 2 [(gogoproto.customtype) = "github.com/hyperledger/burrow/binary.HexBytes", (gogoproto.nullable) = false];
+    // Whether the transaction creates a contract
+    bool CreatesContract = 3;
+    // The address of the contract being called
+    bytes ContractAddress = 4 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.nullable) = false];
+}