From b5762d6541a9e4c2174bfbe1bcfb2dab1fa41e32 Mon Sep 17 00:00:00 2001
From: Silas Davis <silas@monax.io>
Date: Wed, 18 Jul 2018 17:28:04 +0100
Subject: [PATCH] Move account to well-known acm

Signed-off-by: Silas Davis <silas@monax.io>
---
 account/account.go                         | 324 -------------
 account/validator_test.go                  |   1 -
 acm/account.go                             | 241 ++++++++++
 {account => acm}/account_test.go           |  29 +-
 acm/acm.go                                 |   3 +
 acm/acm.pb.go                              | 528 +++++++++++++++++++++
 {account => acm}/bytecode.go               |  20 +-
 {account => acm}/bytecode_test.go          |   2 +-
 {account => acm}/private_account.go        |  97 ++--
 {account => acm}/state/memory_state.go     |   2 +-
 {account => acm}/state/state.go            |  10 +-
 {account => acm}/state/state_cache.go      |   2 +-
 {account => acm}/state/state_cache_test.go |   8 +-
 {account => acm}/validator.go              |   2 +-
 acm/validator_test.go                      |   1 +
 15 files changed, 875 insertions(+), 395 deletions(-)
 delete mode 100644 account/account.go
 delete mode 100644 account/validator_test.go
 create mode 100644 acm/account.go
 rename {account => acm}/account_test.go (79%)
 create mode 100644 acm/acm.go
 create mode 100644 acm/acm.pb.go
 rename {account => acm}/bytecode.go (88%)
 rename {account => acm}/bytecode_test.go (99%)
 rename {account => acm}/private_account.go (52%)
 rename {account => acm}/state/memory_state.go (97%)
 rename {account => acm}/state/state.go (91%)
 rename {account => acm}/state/state_cache.go (99%)
 rename {account => acm}/state/state_cache_test.go (97%)
 rename {account => acm}/validator.go (99%)
 create mode 100644 acm/validator_test.go

diff --git a/account/account.go b/account/account.go
deleted file mode 100644
index a708bb67..00000000
--- a/account/account.go
+++ /dev/null
@@ -1,324 +0,0 @@
-// Copyright 2017 Monax Industries Limited
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package account
-
-import (
-	"encoding/json"
-	"fmt"
-
-	"github.com/hyperledger/burrow/binary"
-	"github.com/hyperledger/burrow/crypto"
-	ptypes "github.com/hyperledger/burrow/permission/types"
-	"github.com/tendermint/go-amino"
-)
-
-var GlobalPermissionsAddress = crypto.Address(binary.Zero160)
-
-type Addressable interface {
-	// Get the 20 byte EVM address of this account
-	Address() crypto.Address
-	// Public key from which the Address is derived
-	PublicKey() crypto.PublicKey
-}
-
-// The default immutable interface to an account
-type Account interface {
-	Addressable
-	// The value held by this account in terms of the chain-native token
-	Balance() uint64
-	// The EVM byte code held by this account (or equivalently, this contract)
-	Code() Bytecode
-	// The sequence number of this account, incremented each time a mutation of the
-	// Account is persisted to the blockchain state
-	Sequence() uint64
-	// The hash of all the values in this accounts storage (typically the root of some subtree
-	// in the merkle tree of global storage state)
-	StorageRoot() []byte
-	// The permission flags and roles for this account
-	Permissions() ptypes.AccountPermissions
-	// Obtain a deterministic serialisation of this account
-	// (i.e. update order and Go runtime independent)
-	Encode() ([]byte, error)
-	// String representation of the account
-	String() string
-}
-
-type MutableAccount interface {
-	Account
-	// Set public key (needed for lazy initialisation), should also set the dependent address
-	SetPublicKey(pubKey crypto.PublicKey) MutableAccount
-	// Subtract amount from account balance (will panic if amount is greater than balance)
-	SubtractFromBalance(amount uint64) (MutableAccount, error)
-	// Add amount to balance (will panic if amount plus balance is a uint64 overflow)
-	AddToBalance(amount uint64) (MutableAccount, error)
-	// Set EVM byte code associated with account
-	SetCode(code []byte) MutableAccount
-	// Increment Sequence number by 1 (capturing the current Sequence number as the index for any pending mutations)
-	IncSequence() MutableAccount
-	// Set the storage root hash
-	SetStorageRoot(storageRoot []byte) MutableAccount
-	// Set account permissions
-	SetPermissions(permissions ptypes.AccountPermissions) MutableAccount
-	// Get a pointer this account's AccountPermissions in order to mutate them
-	MutablePermissions() *ptypes.AccountPermissions
-	// Create a complete copy of this MutableAccount that is itself mutable
-	Copy() MutableAccount
-}
-
-// -------------------------------------------------
-// ConcreteAccount
-
-// ConcreteAccount is the canonical serialisation and bash-in-place object for an Account
-type ConcreteAccount struct {
-	Address     crypto.Address
-	PublicKey   crypto.PublicKey
-	Sequence    uint64
-	Balance     uint64
-	Code        Bytecode
-	StorageRoot []byte
-	Permissions ptypes.AccountPermissions
-}
-
-func NewConcreteAccount(pubKey crypto.PublicKey) ConcreteAccount {
-	return ConcreteAccount{
-		Address:   pubKey.Address(),
-		PublicKey: pubKey,
-	}
-}
-
-func NewConcreteAccountFromSecret(secret string) ConcreteAccount {
-	return NewConcreteAccount(crypto.PrivateKeyFromSecret(secret, crypto.CurveTypeEd25519).GetPublicKey())
-}
-
-// Return as immutable Account
-func (acc ConcreteAccount) Account() Account {
-	return concreteAccountWrapper{&acc}
-}
-
-// Return as mutable MutableAccount
-func (acc ConcreteAccount) MutableAccount() MutableAccount {
-	return concreteAccountWrapper{&acc}
-}
-
-func (acc *ConcreteAccount) Copy() *ConcreteAccount {
-	accCopy := *acc
-	return &accCopy
-}
-
-func (acc *ConcreteAccount) String() string {
-	if acc == nil {
-		return "Account{nil}"
-	}
-
-	return fmt.Sprintf("Account{Address: %s; Sequence: %v; PublicKey: %v Balance: %v; CodeBytes: %v; StorageRoot: 0x%X; Permissions: %s}",
-		acc.Address, acc.Sequence, acc.PublicKey, acc.Balance, len(acc.Code), acc.StorageRoot, acc.Permissions)
-}
-
-// ConcreteAccount
-// -------------------------------------------------
-// Conversions
-//
-// Using the naming convention is this package of 'As<Type>' being
-// a conversion from Account to <Type> and 'From<Type>' being conversion
-// from <Type> to Account. Conversions are done by copying
-
-// Returns a mutable, serialisable ConcreteAccount by copying from account
-func AsConcreteAccount(account Account) *ConcreteAccount {
-	if account == nil {
-		return nil
-	}
-	// Avoid a copy
-	if ca, ok := account.(concreteAccountWrapper); ok {
-		return ca.ConcreteAccount
-	}
-	return &ConcreteAccount{
-		Address:     account.Address(),
-		PublicKey:   account.PublicKey(),
-		Balance:     account.Balance(),
-		Code:        account.Code(),
-		Sequence:    account.Sequence(),
-		StorageRoot: account.StorageRoot(),
-		Permissions: account.Permissions(),
-	}
-}
-
-// Creates an otherwise zeroed Account from an Addressable and returns it as MutableAccount
-func FromAddressable(addressable Addressable) MutableAccount {
-	return ConcreteAccount{
-		Address:   addressable.Address(),
-		PublicKey: addressable.PublicKey(),
-		// Since nil slices and maps compare differently to empty ones
-		Code:        Bytecode{},
-		StorageRoot: []byte{},
-		Permissions: ptypes.AccountPermissions{
-			Roles: []string{},
-		},
-	}.MutableAccount()
-}
-
-// Returns an immutable account by copying from account
-func AsAccount(account Account) Account {
-	if account == nil {
-		return nil
-	}
-	return AsConcreteAccount(account).Account()
-}
-
-// Returns a MutableAccount by copying from account
-func AsMutableAccount(account Account) MutableAccount {
-	if account == nil {
-		return nil
-	}
-	return AsConcreteAccount(account).MutableAccount()
-}
-
-//----------------------------------------------
-// concreteAccount Wrapper
-
-// concreteAccountWrapper wraps ConcreteAccount to provide a immutable read-only view
-// via its implementation of Account and a mutable implementation via its implementation of
-// MutableAccount
-type concreteAccountWrapper struct {
-	*ConcreteAccount `json:"unwrap"`
-}
-
-var _ Account = concreteAccountWrapper{}
-
-func (caw concreteAccountWrapper) Address() crypto.Address {
-	return caw.ConcreteAccount.Address
-}
-
-func (caw concreteAccountWrapper) PublicKey() crypto.PublicKey {
-	return caw.ConcreteAccount.PublicKey
-}
-
-func (caw concreteAccountWrapper) Balance() uint64 {
-	return caw.ConcreteAccount.Balance
-}
-
-func (caw concreteAccountWrapper) Code() Bytecode {
-	return caw.ConcreteAccount.Code
-}
-
-func (caw concreteAccountWrapper) Sequence() uint64 {
-	return caw.ConcreteAccount.Sequence
-}
-
-func (caw concreteAccountWrapper) StorageRoot() []byte {
-	return caw.ConcreteAccount.StorageRoot
-}
-
-func (caw concreteAccountWrapper) Permissions() ptypes.AccountPermissions {
-	return caw.ConcreteAccount.Permissions
-}
-
-func (caw concreteAccountWrapper) Encode() ([]byte, error) {
-	return caw.ConcreteAccount.Encode()
-}
-
-func (caw concreteAccountWrapper) String() string {
-	return caw.ConcreteAccount.String()
-}
-
-func (caw concreteAccountWrapper) MarshalJSON() ([]byte, error) {
-	return json.Marshal(caw.ConcreteAccount)
-}
-
-// Account mutation via MutableAccount interface
-var _ MutableAccount = concreteAccountWrapper{}
-
-func (caw concreteAccountWrapper) SetPublicKey(pubKey crypto.PublicKey) MutableAccount {
-	caw.ConcreteAccount.PublicKey = pubKey
-	addressFromPubKey := pubKey.Address()
-	// We don't want the wrong public key to take control of an account so we panic here
-	if caw.ConcreteAccount.Address != addressFromPubKey {
-		panic(fmt.Errorf("attempt to set public key of account %s to %v, "+
-			"but that public key has address %s",
-			caw.ConcreteAccount.Address, pubKey, addressFromPubKey))
-	}
-	return caw
-}
-
-func (caw concreteAccountWrapper) SubtractFromBalance(amount uint64) (MutableAccount, error) {
-	if amount > caw.Balance() {
-		return nil, fmt.Errorf("insufficient funds: attempt to subtract %v from the balance of %s",
-			amount, caw.ConcreteAccount)
-	}
-	caw.ConcreteAccount.Balance -= amount
-	return caw, nil
-}
-
-func (caw concreteAccountWrapper) AddToBalance(amount uint64) (MutableAccount, error) {
-	if binary.IsUint64SumOverflow(caw.Balance(), amount) {
-		return nil, fmt.Errorf("uint64 overflow: attempt to add %v to the balance of %s",
-			amount, caw.ConcreteAccount)
-	}
-	caw.ConcreteAccount.Balance += amount
-	return caw, nil
-}
-
-func (caw concreteAccountWrapper) SetCode(code []byte) MutableAccount {
-	caw.ConcreteAccount.Code = code
-	return caw
-}
-
-func (caw concreteAccountWrapper) IncSequence() MutableAccount {
-	caw.ConcreteAccount.Sequence += 1
-	return caw
-}
-
-func (caw concreteAccountWrapper) SetStorageRoot(storageRoot []byte) MutableAccount {
-	caw.ConcreteAccount.StorageRoot = storageRoot
-	return caw
-}
-
-func (caw concreteAccountWrapper) SetPermissions(permissions ptypes.AccountPermissions) MutableAccount {
-	caw.ConcreteAccount.Permissions = permissions
-	return caw
-}
-
-func (caw concreteAccountWrapper) MutablePermissions() *ptypes.AccountPermissions {
-	return &caw.ConcreteAccount.Permissions
-}
-
-func (caw concreteAccountWrapper) Copy() MutableAccount {
-	return concreteAccountWrapper{caw.ConcreteAccount.Copy()}
-}
-
-// concreteAccount Wrapper
-//----------------------------------------------
-// Encoding/decoding
-var cdc = amino.NewCodec()
-
-func (acc *ConcreteAccount) Encode() ([]byte, error) {
-	return cdc.MarshalBinary(acc)
-}
-
-func Decode(accBytes []byte) (Account, error) {
-	ca, err := DecodeConcrete(accBytes)
-	if err != nil {
-		return nil, err
-	}
-	return ca.Account(), nil
-}
-
-func DecodeConcrete(accBytes []byte) (*ConcreteAccount, error) {
-	ca := new(ConcreteAccount)
-	err := cdc.UnmarshalBinary(accBytes, ca)
-	if err != nil {
-		return nil, fmt.Errorf("could not convert decoded account to *ConcreteAccount: %v", err)
-	}
-	return ca, nil
-}
diff --git a/account/validator_test.go b/account/validator_test.go
deleted file mode 100644
index 0bc76357..00000000
--- a/account/validator_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package account
diff --git a/acm/account.go b/acm/account.go
new file mode 100644
index 00000000..4c3b1170
--- /dev/null
+++ b/acm/account.go
@@ -0,0 +1,241 @@
+// 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 acm
+
+import (
+	"encoding/json"
+	"fmt"
+
+	"github.com/hyperledger/burrow/binary"
+	"github.com/hyperledger/burrow/crypto"
+	"github.com/hyperledger/burrow/event/query"
+	"github.com/hyperledger/burrow/permission"
+	"github.com/tendermint/go-amino"
+)
+
+var GlobalPermissionsAddress = crypto.Address(binary.Zero160)
+
+type Addressable interface {
+	// Get the 20 byte EVM address of this account
+	Address() crypto.Address
+	// Public key from which the Address is derived
+	PublicKey() crypto.PublicKey
+}
+
+// The default immutable interface to an account
+type Account interface {
+	Addressable
+	// The value held by this account in terms of the chain-native token
+	Balance() uint64
+	// The EVM byte code held by this account (or equivalently, this contract)
+	Code() Bytecode
+	// The sequence number of this account, incremented each time a mutation of the
+	// Account is persisted to the blockchain state
+	Sequence() uint64
+	// The permission flags and roles for this account
+	Permissions() permission.AccountPermissions
+	// Obtain a deterministic serialisation of this account
+	// (i.e. update order and Go runtime independent)
+	Encode() ([]byte, error)
+	// String representation of the account
+	String() string
+	// Get tags for this account
+	Tagged() query.Tagged
+}
+
+// MutableAccount structure
+type MutableAccount struct {
+	concreteAccount *ConcreteAccount
+}
+
+func NewConcreteAccount(pubKey crypto.PublicKey) *ConcreteAccount {
+	return &ConcreteAccount{
+		Address:   pubKey.Address(),
+		PublicKey: pubKey,
+	}
+}
+
+func NewConcreteAccountFromSecret(secret string) *ConcreteAccount {
+	return NewConcreteAccount(crypto.PrivateKeyFromSecret(secret, crypto.CurveTypeEd25519).GetPublicKey())
+}
+
+func (ca ConcreteAccount) Account() Account {
+	return ca.MutableAccount()
+}
+
+// Wrap a copy of ConcreteAccount in a MutableAccount
+func (ca ConcreteAccount) MutableAccount() *MutableAccount {
+	return &MutableAccount{
+		concreteAccount: &ca,
+	}
+}
+
+func (ca ConcreteAccount) Encode() ([]byte, error) {
+	return cdc.MarshalBinary(ca)
+}
+
+func DecodeConcrete(accBytes []byte) (*ConcreteAccount, error) {
+	ca := new(ConcreteAccount)
+	err := cdc.UnmarshalBinary(accBytes, ca)
+	if err != nil {
+		return nil, err
+	}
+	return ca, nil
+}
+
+// Conversions
+//
+// Using the naming convention is this package of 'As<Type>' being
+// a conversion from Account to <Type> and 'From<Type>' being conversion
+// from <Type> to Account. Conversions are done by copying
+
+// Returns a mutable, serialisable ConcreteAccount by copying from account
+func AsConcreteAccount(account Account) *ConcreteAccount {
+	if account == nil {
+		return nil
+	}
+	return &ConcreteAccount{
+		Address:     account.Address(),
+		PublicKey:   account.PublicKey(),
+		Balance:     account.Balance(),
+		Code:        account.Code(),
+		Sequence:    account.Sequence(),
+		Permissions: account.Permissions(),
+	}
+}
+
+// Creates an otherwise zeroed Account from an Addressable and returns it as MutableAccount
+func FromAddressable(addressable Addressable) *MutableAccount {
+	ca := &ConcreteAccount{
+		Address:   addressable.Address(),
+		PublicKey: addressable.PublicKey(),
+		// Since nil slices and maps compare differently to empty ones
+		Code: Bytecode{},
+		Permissions: permission.AccountPermissions{
+			Roles: []string{},
+		},
+	}
+	return ca.MutableAccount()
+}
+
+// Returns a MutableAccount by copying from account
+func AsMutableAccount(account Account) *MutableAccount {
+	if account == nil {
+		return nil
+	}
+	return AsConcreteAccount(account).MutableAccount()
+}
+
+func (acc ConcreteAccount) String() string {
+	return fmt.Sprintf("ConcreteAccount{Address: %s; Sequence: %v; PublicKey: %v Balance: %v; CodeLength: %v; Permissions: %s}",
+		acc.Address, acc.Sequence, acc.PublicKey, acc.Balance, len(acc.Code), acc.Permissions)
+}
+
+///---- Getter methods
+func (acc MutableAccount) Address() crypto.Address     { return acc.concreteAccount.Address }
+func (acc MutableAccount) PublicKey() crypto.PublicKey { return acc.concreteAccount.PublicKey }
+func (acc MutableAccount) Balance() uint64             { return acc.concreteAccount.Balance }
+func (acc MutableAccount) Code() Bytecode              { return acc.concreteAccount.Code }
+func (acc MutableAccount) Sequence() uint64            { return acc.concreteAccount.Sequence }
+func (acc MutableAccount) Permissions() permission.AccountPermissions {
+	return acc.concreteAccount.Permissions
+}
+
+///---- Mutable methods
+// Set public key (needed for lazy initialisation), should also set the dependent address
+func (acc *MutableAccount) SetPublicKey(publicKey crypto.PublicKey) {
+	acc.concreteAccount.PublicKey = publicKey
+}
+
+func (acc *MutableAccount) SubtractFromBalance(amount uint64) error {
+	if amount > acc.Balance() {
+		return fmt.Errorf("insufficient funds: attempt to subtract %v from the balance of %s",
+			amount, acc.Address())
+	}
+	acc.concreteAccount.Balance -= amount
+	return nil
+}
+
+func (acc *MutableAccount) AddToBalance(amount uint64) error {
+	if binary.IsUint64SumOverflow(acc.Balance(), amount) {
+		return fmt.Errorf("uint64 overflow: attempt to add %v to the balance of %s",
+			amount, acc.Address())
+	}
+	acc.concreteAccount.Balance += amount
+	return nil
+}
+
+func (acc *MutableAccount) SetCode(code []byte) error {
+	acc.concreteAccount.Code = code
+	return nil
+}
+
+func (acc *MutableAccount) IncSequence() {
+	acc.concreteAccount.Sequence++
+}
+
+func (acc *MutableAccount) SetPermissions(permissions permission.AccountPermissions) error {
+	acc.concreteAccount.Permissions = permissions
+	return nil
+}
+
+func (acc *MutableAccount) MutablePermissions() *permission.AccountPermissions {
+	return &acc.concreteAccount.Permissions
+}
+
+type TaggedAccount struct {
+	*MutableAccount
+	query.Tagged
+}
+
+func (acc *MutableAccount) Tagged() query.Tagged {
+	return &TaggedAccount{
+		MutableAccount: acc,
+		Tagged:         query.MustReflectTags(acc),
+	}
+}
+
+///---- Serialisation methods
+
+var cdc = amino.NewCodec()
+
+func (acc MutableAccount) Encode() ([]byte, error) {
+	return acc.concreteAccount.Encode()
+}
+
+func Decode(accBytes []byte) (*MutableAccount, error) {
+	ca, err := DecodeConcrete(accBytes)
+	if err != nil {
+		return nil, err
+	}
+	return &MutableAccount{
+		concreteAccount: ca,
+	}, nil
+}
+
+func (acc MutableAccount) MarshalJSON() ([]byte, error) {
+	return json.Marshal(acc.concreteAccount)
+}
+func (acc *MutableAccount) UnmarshalJSON(bytes []byte) error {
+	err := json.Unmarshal(bytes, &acc.concreteAccount)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (acc MutableAccount) String() string {
+	return fmt.Sprintf("MutableAccount{%s}", acc.concreteAccount.String())
+}
diff --git a/account/account_test.go b/acm/account_test.go
similarity index 79%
rename from account/account_test.go
rename to acm/account_test.go
index 5e8f0ed3..af55ec50 100644
--- a/account/account_test.go
+++ b/acm/account_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package account
+package acm
 
 import (
 	"testing"
@@ -22,7 +22,7 @@ import (
 	"fmt"
 
 	"github.com/hyperledger/burrow/crypto"
-	ptypes "github.com/hyperledger/burrow/permission/types"
+	"github.com/hyperledger/burrow/permission"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 )
@@ -50,21 +50,21 @@ func TestAddress(t *testing.T) {
 
 func TestDecodeConcrete(t *testing.T) {
 	concreteAcc := NewConcreteAccountFromSecret("Super Semi Secret")
-	concreteAcc.Permissions = ptypes.AccountPermissions{
-		Base: ptypes.BasePermissions{
-			Perms:  ptypes.SetGlobal,
-			SetBit: ptypes.SetGlobal,
+	concreteAcc.Permissions = permission.AccountPermissions{
+		Base: permission.BasePermissions{
+			Perms:  permission.SetGlobal,
+			SetBit: permission.SetGlobal,
 		},
 		Roles: []string{"bums"},
 	}
-	acc := concreteAcc.Account()
+	acc := concreteAcc
 	encodedAcc, err := acc.Encode()
 	require.NoError(t, err)
 
 	concreteAccOut, err := DecodeConcrete(encodedAcc)
 	require.NoError(t, err)
 
-	assert.Equal(t, concreteAcc, *concreteAccOut)
+	assert.Equal(t, concreteAcc, concreteAccOut)
 	concreteAccOut, err = DecodeConcrete([]byte("flungepliffery munknut tolopops"))
 	assert.Error(t, err)
 }
@@ -76,7 +76,7 @@ func TestDecode(t *testing.T) {
 	require.NoError(t, err)
 	accOut, err := Decode(encodedAcc)
 	require.NoError(t, err)
-	assert.Equal(t, concreteAcc, *AsConcreteAccount(accOut))
+	assert.Equal(t, concreteAcc, AsConcreteAccount(accOut))
 
 	accOut, err = Decode([]byte("flungepliffery munknut tolopops"))
 	require.Error(t, err)
@@ -86,12 +86,19 @@ func TestDecode(t *testing.T) {
 func TestMarshalJSON(t *testing.T) {
 	concreteAcc := NewConcreteAccountFromSecret("Super Semi Secret")
 	concreteAcc.Code = []byte{60, 23, 45}
+	concreteAcc.Permissions = permission.AccountPermissions{
+		Base: permission.BasePermissions{
+			Perms: permission.AllPermFlags,
+		},
+	}
+	concreteAcc.Sequence = 4
+	concreteAcc.Balance = 10
 	acc := concreteAcc.Account()
 	bs, err := json.Marshal(acc)
 
 	expected := fmt.Sprintf(`{"Address":"%s","PublicKey":{"CurveType":"ed25519","PublicKey":"%s"},`+
-		`"Sequence":0,"Balance":0,"Code":"3C172D","StorageRoot":null,`+
-		`"Permissions":{"Base":{"Perms":0,"SetBit":0},"Roles":null}}`,
+		`"Sequence":4,"Balance":10,"Code":"3C172D",`+
+		`"Permissions":{"Base":{"Perms":16383,"SetBit":0}}}`,
 		concreteAcc.Address, concreteAcc.PublicKey)
 	assert.Equal(t, expected, string(bs))
 	assert.NoError(t, err)
diff --git a/acm/acm.go b/acm/acm.go
new file mode 100644
index 00000000..9b84345b
--- /dev/null
+++ b/acm/acm.go
@@ -0,0 +1,3 @@
+// The acm package contains code relating to accounts and account state
+// the abbreviation probably derives from 'ACcount Management'
+package acm
diff --git a/acm/acm.pb.go b/acm/acm.pb.go
new file mode 100644
index 00000000..98896e1d
--- /dev/null
+++ b/acm/acm.pb.go
@@ -0,0 +1,528 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: acm.proto
+
+/*
+	Package acm is a generated protocol buffer package.
+
+	It is generated from these files:
+		acm.proto
+
+	It has these top-level messages:
+		ConcreteAccount
+*/
+package acm
+
+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 permission "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 ConcreteAccount struct {
+	Address     github_com_hyperledger_burrow_crypto.Address `protobuf:"bytes,1,opt,name=Address,proto3,customtype=github.com/hyperledger/burrow/crypto.Address" json:"Address"`
+	PublicKey   crypto.PublicKey                             `protobuf:"bytes,2,opt,name=PublicKey" json:"PublicKey"`
+	Sequence    uint64                                       `protobuf:"varint,3,opt,name=Sequence,proto3" json:"Sequence,omitempty"`
+	Balance     uint64                                       `protobuf:"varint,4,opt,name=Balance,proto3" json:"Balance,omitempty"`
+	Code        Bytecode                                     `protobuf:"bytes,5,opt,name=Code,proto3,customtype=Bytecode" json:"Code"`
+	Permissions permission.AccountPermissions                `protobuf:"bytes,6,opt,name=Permissions" json:"Permissions"`
+}
+
+func (m *ConcreteAccount) Reset()                    { *m = ConcreteAccount{} }
+func (*ConcreteAccount) ProtoMessage()               {}
+func (*ConcreteAccount) Descriptor() ([]byte, []int) { return fileDescriptorAcm, []int{0} }
+
+func (m *ConcreteAccount) GetPublicKey() crypto.PublicKey {
+	if m != nil {
+		return m.PublicKey
+	}
+	return crypto.PublicKey{}
+}
+
+func (m *ConcreteAccount) GetSequence() uint64 {
+	if m != nil {
+		return m.Sequence
+	}
+	return 0
+}
+
+func (m *ConcreteAccount) GetBalance() uint64 {
+	if m != nil {
+		return m.Balance
+	}
+	return 0
+}
+
+func (m *ConcreteAccount) GetPermissions() permission.AccountPermissions {
+	if m != nil {
+		return m.Permissions
+	}
+	return permission.AccountPermissions{}
+}
+
+func (*ConcreteAccount) XXX_MessageName() string {
+	return "acm.ConcreteAccount"
+}
+func init() {
+	proto.RegisterType((*ConcreteAccount)(nil), "acm.ConcreteAccount")
+	golang_proto.RegisterType((*ConcreteAccount)(nil), "acm.ConcreteAccount")
+}
+func (m *ConcreteAccount) 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 *ConcreteAccount) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	dAtA[i] = 0xa
+	i++
+	i = encodeVarintAcm(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 = encodeVarintAcm(dAtA, i, uint64(m.PublicKey.Size()))
+	n2, err := m.PublicKey.MarshalTo(dAtA[i:])
+	if err != nil {
+		return 0, err
+	}
+	i += n2
+	if m.Sequence != 0 {
+		dAtA[i] = 0x18
+		i++
+		i = encodeVarintAcm(dAtA, i, uint64(m.Sequence))
+	}
+	if m.Balance != 0 {
+		dAtA[i] = 0x20
+		i++
+		i = encodeVarintAcm(dAtA, i, uint64(m.Balance))
+	}
+	dAtA[i] = 0x2a
+	i++
+	i = encodeVarintAcm(dAtA, i, uint64(m.Code.Size()))
+	n3, err := m.Code.MarshalTo(dAtA[i:])
+	if err != nil {
+		return 0, err
+	}
+	i += n3
+	dAtA[i] = 0x32
+	i++
+	i = encodeVarintAcm(dAtA, i, uint64(m.Permissions.Size()))
+	n4, err := m.Permissions.MarshalTo(dAtA[i:])
+	if err != nil {
+		return 0, err
+	}
+	i += n4
+	return i, nil
+}
+
+func encodeVarintAcm(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 *ConcreteAccount) Size() (n int) {
+	var l int
+	_ = l
+	l = m.Address.Size()
+	n += 1 + l + sovAcm(uint64(l))
+	l = m.PublicKey.Size()
+	n += 1 + l + sovAcm(uint64(l))
+	if m.Sequence != 0 {
+		n += 1 + sovAcm(uint64(m.Sequence))
+	}
+	if m.Balance != 0 {
+		n += 1 + sovAcm(uint64(m.Balance))
+	}
+	l = m.Code.Size()
+	n += 1 + l + sovAcm(uint64(l))
+	l = m.Permissions.Size()
+	n += 1 + l + sovAcm(uint64(l))
+	return n
+}
+
+func sovAcm(x uint64) (n int) {
+	for {
+		n++
+		x >>= 7
+		if x == 0 {
+			break
+		}
+	}
+	return n
+}
+func sozAcm(x uint64) (n int) {
+	return sovAcm(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *ConcreteAccount) 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 ErrIntOverflowAcm
+			}
+			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: ConcreteAccount: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: ConcreteAccount: 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 ErrIntOverflowAcm
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthAcm
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			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 ErrIntOverflowAcm
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthAcm
+			}
+			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 Sequence", wireType)
+			}
+			m.Sequence = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowAcm
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Sequence |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 4:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Balance", wireType)
+			}
+			m.Balance = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowAcm
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Balance |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 5:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowAcm
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthAcm
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.Code.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)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowAcm
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthAcm
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.Permissions.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipAcm(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthAcm
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipAcm(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, ErrIntOverflowAcm
+			}
+			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, ErrIntOverflowAcm
+				}
+				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, ErrIntOverflowAcm
+				}
+				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, ErrInvalidLengthAcm
+			}
+			return iNdEx, nil
+		case 3:
+			for {
+				var innerWire uint64
+				var start int = iNdEx
+				for shift := uint(0); ; shift += 7 {
+					if shift >= 64 {
+						return 0, ErrIntOverflowAcm
+					}
+					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 := skipAcm(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 (
+	ErrInvalidLengthAcm = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowAcm   = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("acm.proto", fileDescriptorAcm) }
+func init() { golang_proto.RegisterFile("acm.proto", fileDescriptorAcm) }
+
+var fileDescriptorAcm = []byte{
+	// 330 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x91, 0xbd, 0x4e, 0xfb, 0x30,
+	0x14, 0xc5, 0xeb, 0x36, 0xff, 0x7e, 0xb8, 0x95, 0xfe, 0xc5, 0x53, 0xd4, 0xc1, 0x2d, 0x88, 0xa1,
+	0x03, 0x24, 0x12, 0x1f, 0x42, 0x62, 0x6b, 0x2a, 0xb1, 0x20, 0xa1, 0x2a, 0x6c, 0x6c, 0x89, 0x73,
+	0x49, 0x23, 0x35, 0x71, 0x70, 0x6c, 0xa1, 0xbc, 0x09, 0x23, 0x8f, 0x82, 0x98, 0x3a, 0x32, 0x33,
+	0x54, 0xa8, 0x7d, 0x11, 0x54, 0xe3, 0x96, 0x4c, 0x6c, 0x39, 0xf9, 0xdd, 0x73, 0xef, 0xd1, 0x31,
+	0xee, 0x04, 0x2c, 0x75, 0x72, 0xc1, 0x25, 0x27, 0x8d, 0x80, 0xa5, 0x83, 0xd3, 0x38, 0x91, 0x73,
+	0x15, 0x3a, 0x8c, 0xa7, 0x6e, 0xcc, 0x63, 0xee, 0x6a, 0x16, 0xaa, 0x47, 0xad, 0xb4, 0xd0, 0x5f,
+	0x3f, 0x9e, 0x41, 0x3f, 0x07, 0x91, 0x26, 0x45, 0x91, 0xf0, 0xcc, 0xfc, 0xe9, 0x31, 0x51, 0xe6,
+	0xd2, 0xf0, 0xa3, 0xf7, 0x3a, 0xfe, 0x3f, 0xe5, 0x19, 0x13, 0x20, 0x61, 0xc2, 0x18, 0x57, 0x99,
+	0x24, 0x77, 0xb8, 0x35, 0x89, 0x22, 0x01, 0x45, 0x61, 0xa3, 0x11, 0x1a, 0xf7, 0xbc, 0x8b, 0xe5,
+	0x6a, 0x58, 0xfb, 0x5c, 0x0d, 0x4f, 0x2a, 0xb7, 0xe7, 0x65, 0x0e, 0x62, 0x01, 0x51, 0x0c, 0xc2,
+	0x0d, 0x95, 0x10, 0xfc, 0xd9, 0x35, 0x8b, 0x8d, 0xd7, 0xdf, 0x2d, 0x21, 0x97, 0xb8, 0x33, 0x53,
+	0xe1, 0x22, 0x61, 0xb7, 0x50, 0xda, 0xf5, 0x11, 0x1a, 0x77, 0xcf, 0x0e, 0x1c, 0x33, 0xbc, 0x07,
+	0x9e, 0xb5, 0x3d, 0xe2, 0xff, 0x4e, 0x92, 0x01, 0x6e, 0xdf, 0xc3, 0x93, 0x82, 0x8c, 0x81, 0xdd,
+	0x18, 0xa1, 0xb1, 0xe5, 0xef, 0x35, 0xb1, 0x71, 0xcb, 0x0b, 0x16, 0xc1, 0x16, 0x59, 0x1a, 0xed,
+	0x24, 0x39, 0xc6, 0xd6, 0x94, 0x47, 0x60, 0xff, 0xd3, 0xc9, 0xfb, 0x26, 0x79, 0xdb, 0x2b, 0x25,
+	0x30, 0x1e, 0x81, 0xaf, 0x29, 0xb9, 0xc1, 0xdd, 0xd9, 0xbe, 0x98, 0xc2, 0x6e, 0xea, 0x50, 0xd4,
+	0xa9, 0x94, 0x65, 0xca, 0xa8, 0x4c, 0x99, 0x84, 0x55, 0xe3, 0xb5, 0xf5, 0xf2, 0x3a, 0xac, 0x79,
+	0x57, 0xcb, 0x35, 0x45, 0x1f, 0x6b, 0x8a, 0xbe, 0xd6, 0x14, 0xbd, 0x6d, 0x28, 0x5a, 0x6e, 0x28,
+	0x7a, 0x38, 0xfc, 0xbb, 0xad, 0x80, 0xa5, 0x61, 0x53, 0x3f, 0xc2, 0xf9, 0x77, 0x00, 0x00, 0x00,
+	0xff, 0xff, 0x5b, 0x02, 0x22, 0xf4, 0xe5, 0x01, 0x00, 0x00,
+}
diff --git a/account/bytecode.go b/acm/bytecode.go
similarity index 88%
rename from account/bytecode.go
rename to acm/bytecode.go
index 01a1cdad..bb926242 100644
--- a/account/bytecode.go
+++ b/acm/bytecode.go
@@ -1,4 +1,4 @@
-package account
+package acm
 
 import (
 	"encoding/json"
@@ -64,6 +64,24 @@ func (bc *Bytecode) UnmarshalText(text []byte) error {
 	return err
 }
 
+// Protobuf support
+func (bc Bytecode) Marshal() ([]byte, error) {
+	return bc, nil
+}
+
+func (bc *Bytecode) Unmarshal(data []byte) error {
+	*bc = data
+	return nil
+}
+
+func (bc Bytecode) MarshalTo(data []byte) (int, error) {
+	return copy(data, bc), nil
+}
+
+func (bc Bytecode) Size() int {
+	return len(bc)
+}
+
 // Tokenises the bytecode into opcodes and values
 func (bc Bytecode) Tokens() ([]string, error) {
 	// Overestimate of capacity in the presence of pushes
diff --git a/account/bytecode_test.go b/acm/bytecode_test.go
similarity index 99%
rename from account/bytecode_test.go
rename to acm/bytecode_test.go
index 00f1bd0c..462a4cb7 100644
--- a/account/bytecode_test.go
+++ b/acm/bytecode_test.go
@@ -1,4 +1,4 @@
-package account
+package acm
 
 import (
 	"encoding/json"
diff --git a/account/private_account.go b/acm/private_account.go
similarity index 52%
rename from account/private_account.go
rename to acm/private_account.go
index 204096c1..f9cf705d 100644
--- a/account/private_account.go
+++ b/acm/private_account.go
@@ -12,11 +12,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package account
+package acm
 
 import (
 	"fmt"
 
+	"encoding/json"
+
 	"github.com/hyperledger/burrow/crypto"
 )
 
@@ -25,80 +27,85 @@ type AddressableSigner interface {
 	crypto.Signer
 }
 
-type PrivateAccount interface {
-	AddressableSigner
-	PrivateKey() crypto.PrivateKey
+type PrivateAccount struct {
+	concretePrivateAccount *ConcretePrivateAccount
 }
 
-//
-type ConcretePrivateAccount struct {
-	Address    crypto.Address
-	PublicKey  crypto.PublicKey
-	PrivateKey crypto.PrivateKey
+func (pa *PrivateAccount) Address() crypto.Address {
+	return pa.concretePrivateAccount.Address
 }
 
-type concretePrivateAccountWrapper struct {
-	*ConcretePrivateAccount `json:"unwrap"`
+func (pa *PrivateAccount) PublicKey() crypto.PublicKey {
+	return pa.concretePrivateAccount.PublicKey
 }
 
-var _ PrivateAccount = concretePrivateAccountWrapper{}
+func (pa *PrivateAccount) Sign(msg []byte) (crypto.Signature, error) {
+	return pa.concretePrivateAccount.PrivateKey.Sign(msg)
+}
 
-func AsConcretePrivateAccount(privateAccount PrivateAccount) *ConcretePrivateAccount {
-	if privateAccount == nil {
-		return nil
-	}
-	// Avoid a copy
-	if ca, ok := privateAccount.(concretePrivateAccountWrapper); ok {
-		return ca.ConcretePrivateAccount
-	}
-	return &ConcretePrivateAccount{
-		Address:    privateAccount.Address(),
-		PublicKey:  privateAccount.PublicKey(),
-		PrivateKey: privateAccount.PrivateKey(),
-	}
+func (pa PrivateAccount) MarshalJSON() ([]byte, error) {
+	return json.Marshal(pa.concretePrivateAccount)
 }
 
-func (cpaw concretePrivateAccountWrapper) Address() crypto.Address {
-	return cpaw.ConcretePrivateAccount.Address
+func (pa *PrivateAccount) UnmarshalJSON(bytes []byte) error {
+	err := json.Unmarshal(bytes, &pa.concretePrivateAccount)
+	if err != nil {
+		return err
+	}
+	return nil
 }
 
-func (cpaw concretePrivateAccountWrapper) PublicKey() crypto.PublicKey {
-	return cpaw.ConcretePrivateAccount.PublicKey
+func (pa *PrivateAccount) PrivateKey() crypto.PrivateKey {
+	return pa.concretePrivateAccount.PrivateKey
 }
 
-func (cpaw concretePrivateAccountWrapper) PrivateKey() crypto.PrivateKey {
-	return cpaw.ConcretePrivateAccount.PrivateKey
+func (pa *PrivateAccount) ConcretePrivateAccount() *ConcretePrivateAccount {
+	cpa := *pa.concretePrivateAccount
+	return &cpa
 }
 
-func (cpaw concretePrivateAccountWrapper) String() string {
-	return cpaw.ConcretePrivateAccount.String()
+func (pa *PrivateAccount) String() string {
+	return fmt.Sprintf("PrivateAccount{%v}", pa.Address())
 }
 
-// ConcretePrivateAccount
+type ConcretePrivateAccount struct {
+	Address    crypto.Address
+	PublicKey  crypto.PublicKey
+	PrivateKey crypto.PrivateKey
+}
 
-func (pa ConcretePrivateAccount) PrivateAccount() PrivateAccount {
-	return concretePrivateAccountWrapper{ConcretePrivateAccount: &pa}
+func (cpa *ConcretePrivateAccount) String() string {
+	return fmt.Sprintf("ConcretePrivateAccount{%v}", cpa.Address)
 }
 
-func (pa ConcretePrivateAccount) Sign(msg []byte) (crypto.Signature, error) {
-	return pa.PrivateKey.Sign(msg)
+func (cpa ConcretePrivateAccount) PrivateAccount() *PrivateAccount {
+	return &PrivateAccount{
+		concretePrivateAccount: &cpa,
+	}
 }
 
-func (pa *ConcretePrivateAccount) String() string {
-	return fmt.Sprintf("ConcretePrivateAccount{%s}", pa.Address)
+func PrivateAccountFromPrivateKey(privateKey crypto.PrivateKey) *PrivateAccount {
+	publicKey := privateKey.GetPublicKey()
+	return &PrivateAccount{
+		concretePrivateAccount: &ConcretePrivateAccount{
+			PrivateKey: privateKey,
+			PublicKey:  publicKey,
+			Address:    publicKey.Address(),
+		},
+	}
 }
 
 // Convert slice of ConcretePrivateAccounts to slice of SigningAccounts
-func SigningAccounts(concretePrivateAccounts []*ConcretePrivateAccount) []AddressableSigner {
+func SigningAccounts(concretePrivateAccounts []*PrivateAccount) []AddressableSigner {
 	signingAccounts := make([]AddressableSigner, len(concretePrivateAccounts))
 	for i, cpa := range concretePrivateAccounts {
-		signingAccounts[i] = cpa.PrivateAccount()
+		signingAccounts[i] = cpa
 	}
 	return signingAccounts
 }
 
 // Generates a new account with private key.
-func GeneratePrivateAccount() (PrivateAccount, error) {
+func GeneratePrivateAccount() (*PrivateAccount, error) {
 	privateKey, err := crypto.GeneratePrivateKey(nil, crypto.CurveTypeEd25519)
 	if err != nil {
 		return nil, err
@@ -112,7 +119,7 @@ func GeneratePrivateAccount() (PrivateAccount, error) {
 }
 
 // Generates a new account with private key from SHA256 hash of a secret
-func GeneratePrivateAccountFromSecret(secret string) PrivateAccount {
+func GeneratePrivateAccountFromSecret(secret string) *PrivateAccount {
 	privateKey := crypto.PrivateKeyFromSecret(secret, crypto.CurveTypeEd25519)
 	publicKey := privateKey.GetPublicKey()
 	return ConcretePrivateAccount{
@@ -122,7 +129,7 @@ func GeneratePrivateAccountFromSecret(secret string) PrivateAccount {
 	}.PrivateAccount()
 }
 
-func GeneratePrivateAccountFromPrivateKeyBytes(privKeyBytes []byte) (PrivateAccount, error) {
+func PrivateAccountFromPrivateKeyBytes(privKeyBytes []byte) (*PrivateAccount, error) {
 	privateKey, err := crypto.PrivateKeyFromRawBytes(privKeyBytes, crypto.CurveTypeEd25519)
 	if err != nil {
 		return nil, err
diff --git a/account/state/memory_state.go b/acm/state/memory_state.go
similarity index 97%
rename from account/state/memory_state.go
rename to acm/state/memory_state.go
index 605ecd05..937430c5 100644
--- a/account/state/memory_state.go
+++ b/acm/state/memory_state.go
@@ -3,7 +3,7 @@ package state
 import (
 	"fmt"
 
-	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/acm"
 	"github.com/hyperledger/burrow/binary"
 	"github.com/hyperledger/burrow/crypto"
 )
diff --git a/account/state/state.go b/acm/state/state.go
similarity index 91%
rename from account/state/state.go
rename to acm/state/state.go
index 95389ad3..1c2f06a6 100644
--- a/account/state/state.go
+++ b/acm/state/state.go
@@ -1,10 +1,10 @@
 package state
 
 import (
-	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/acm"
 	"github.com/hyperledger/burrow/binary"
 	"github.com/hyperledger/burrow/crypto"
-	ptypes "github.com/hyperledger/burrow/permission/types"
+	"github.com/hyperledger/burrow/permission"
 )
 
 type AccountGetter interface {
@@ -81,7 +81,7 @@ type IterableReaderWriter interface {
 	Writer
 }
 
-func GetMutableAccount(getter AccountGetter, address crypto.Address) (acm.MutableAccount, error) {
+func GetMutableAccount(getter AccountGetter, address crypto.Address) (*acm.MutableAccount, error) {
 	acc, err := getter.GetAccount(address)
 	if err != nil {
 		return nil, err
@@ -98,9 +98,9 @@ func GlobalPermissionsAccount(getter AccountGetter) acm.Account {
 }
 
 // Get global permissions from the account at GlobalPermissionsAddress
-func GlobalAccountPermissions(getter AccountGetter) ptypes.AccountPermissions {
+func GlobalAccountPermissions(getter AccountGetter) permission.AccountPermissions {
 	if getter == nil {
-		return ptypes.AccountPermissions{
+		return permission.AccountPermissions{
 			Roles: []string{},
 		}
 	}
diff --git a/account/state/state_cache.go b/acm/state/state_cache.go
similarity index 99%
rename from account/state/state_cache.go
rename to acm/state/state_cache.go
index 4daf7687..968f2867 100644
--- a/account/state/state_cache.go
+++ b/acm/state/state_cache.go
@@ -19,7 +19,7 @@ import (
 	"sort"
 	"sync"
 
-	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/acm"
 	"github.com/hyperledger/burrow/binary"
 	"github.com/hyperledger/burrow/crypto"
 )
diff --git a/account/state/state_cache_test.go b/acm/state/state_cache_test.go
similarity index 97%
rename from account/state/state_cache_test.go
rename to acm/state/state_cache_test.go
index 6df18eb9..ef975d82 100644
--- a/account/state/state_cache_test.go
+++ b/acm/state/state_cache_test.go
@@ -4,11 +4,11 @@ import (
 	"fmt"
 	"testing"
 
-	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/acm"
 	"github.com/hyperledger/burrow/binary"
 	"github.com/hyperledger/burrow/crypto"
 	"github.com/hyperledger/burrow/execution/evm/asm"
-	ptypes "github.com/hyperledger/burrow/permission/types"
+	"github.com/hyperledger/burrow/permission"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 )
@@ -289,11 +289,11 @@ func TestStateCache_get(t *testing.T) {
 
 func testAccounts() *MemoryState {
 	acc1 := acm.NewConcreteAccountFromSecret("acc1")
-	acc1.Permissions.Base.Perms = ptypes.AddRole | ptypes.Send
+	acc1.Permissions.Base.Perms = permission.AddRole | permission.Send
 	acc1.Permissions.Base.SetBit = acc1.Permissions.Base.Perms
 
 	acc2 := acm.NewConcreteAccountFromSecret("acc2")
-	acc2.Permissions.Base.Perms = ptypes.AddRole | ptypes.Send
+	acc2.Permissions.Base.Perms = permission.AddRole | permission.Send
 	acc2.Permissions.Base.SetBit = acc1.Permissions.Base.Perms
 	acc2.Code, _ = acm.NewBytecode(asm.PUSH1, 0x20)
 
diff --git a/account/validator.go b/acm/validator.go
similarity index 99%
rename from account/validator.go
rename to acm/validator.go
index 121b76fd..51027539 100644
--- a/account/validator.go
+++ b/acm/validator.go
@@ -1,4 +1,4 @@
-package account
+package acm
 
 import (
 	"encoding/json"
diff --git a/acm/validator_test.go b/acm/validator_test.go
new file mode 100644
index 00000000..51299081
--- /dev/null
+++ b/acm/validator_test.go
@@ -0,0 +1 @@
+package acm
-- 
GitLab