diff --git a/config/source/source.go b/config/source/source.go
new file mode 100644
index 0000000000000000000000000000000000000000..b4a31d809bb6d150eaaaa7af1b2c17522fc39d45
--- /dev/null
+++ b/config/source/source.go
@@ -0,0 +1,283 @@
+package source
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"reflect"
+	"strings"
+
+	"github.com/BurntSushi/toml"
+	"github.com/cep21/xdgbasedir"
+	"github.com/imdario/mergo"
+)
+
+// If passed this identifier try to read config from STDIN
+const STDINFileIdentifier = "-"
+
+type ConfigProvider interface {
+	// Description of where this provider sources its config from
+	From() string
+	// Get the config values to the passed in baseConfig
+	Apply(baseConfig interface{}) error
+	// Return a copy of the provider that does nothing if skip is true
+	SetSkip(skip bool) ConfigProvider
+	// Whether to skip this provider
+	Skip() bool
+}
+
+var _ ConfigProvider = &configSource{}
+
+type configSource struct {
+	from  string
+	skip  bool
+	apply func(baseConfig interface{}) error
+}
+
+func NewConfigProvider(from string, skip bool, apply func(baseConfig interface{}) error) *configSource {
+	return &configSource{
+		from:  from,
+		skip:  skip,
+		apply: apply,
+	}
+}
+
+func (cs *configSource) From() string {
+	return cs.from
+}
+
+func (cs *configSource) Apply(baseConfig interface{}) error {
+	return cs.apply(baseConfig)
+}
+
+func (cs *configSource) Skip() bool {
+	return cs.skip
+}
+
+// Returns a copy of the configSource with skip set as passed in
+func (cs *configSource) SetSkip(skip bool) ConfigProvider {
+	return &configSource{
+		skip:  skip,
+		from:  cs.from,
+		apply: cs.apply,
+	}
+}
+
+// Builds a ConfigProvider by iterating over a cascade of ConfigProvider sources. Can be used
+// in two distinct modes: with shortCircuit true the first successful ConfigProvider source
+// is returned. With shortCircuit false sources appearing later are used to possibly override
+// those appearing earlier
+func Cascade(logWriter io.Writer, shortCircuit bool, providers ...ConfigProvider) *configSource {
+	var fromStrings []string
+	skip := true
+	for _, provider := range providers {
+		if !provider.Skip() {
+			skip = false
+			fromStrings = append(fromStrings, provider.From())
+		}
+	}
+	fromPrefix := "each of"
+	if shortCircuit {
+		fromPrefix = "first of"
+
+	}
+	return &configSource{
+		skip: skip,
+		from: fmt.Sprintf("%s: %s", fromPrefix, strings.Join(fromStrings, " then ")),
+		apply: func(baseConfig interface{}) error {
+			if baseConfig == nil {
+				return fmt.Errorf("baseConfig passed to Cascade(...).Get() must not be nil")
+			}
+			for _, provider := range providers {
+				if !provider.Skip() {
+					writeLog(logWriter, fmt.Sprintf("Sourcing config from %s", provider.From()))
+					err := provider.Apply(baseConfig)
+					if err != nil {
+						return err
+					}
+					if shortCircuit {
+						return nil
+					}
+				}
+			}
+			return nil
+		},
+	}
+}
+
+func FirstOf(providers ...ConfigProvider) *configSource {
+	return Cascade(os.Stderr, true, providers...)
+}
+
+func EachOf(providers ...ConfigProvider) *configSource {
+	return Cascade(os.Stderr, false, providers...)
+}
+
+// Try to source config from provided JSON file, is skipNonExistent is true then the provider will fall-through (skip)
+// when the file doesn't exist, rather than returning an error
+func JSONFile(configFile string, skipNonExistent bool) *configSource {
+	return &configSource{
+		skip: ShouldSkipFile(configFile, skipNonExistent),
+		from: fmt.Sprintf("JSON config file at '%s'", configFile),
+		apply: func(baseConfig interface{}) error {
+			return FromJSONFile(configFile, baseConfig)
+		},
+	}
+}
+
+// Try to source config from provided TOML file, is skipNonExistent is true then the provider will fall-through (skip)
+// when the file doesn't exist, rather than returning an error
+func TOMLFile(configFile string, skipNonExistent bool) *configSource {
+	return &configSource{
+		skip: ShouldSkipFile(configFile, skipNonExistent),
+		from: fmt.Sprintf("TOML config file at '%s'", configFile),
+		apply: func(baseConfig interface{}) error {
+			return FromTOMLFile(configFile, baseConfig)
+		},
+	}
+}
+
+// Try to find config by using XDG base dir spec
+func XDGBaseDir(configFileName string) *configSource {
+	skip := false
+	// Look for config in standard XDG specified locations
+	configFile, err := xdgbasedir.GetConfigFileLocation(configFileName)
+	if err == nil {
+		_, err := os.Stat(configFile)
+		// Skip if config  file does not exist at default location
+		skip = os.IsNotExist(err)
+	}
+	return &configSource{
+		skip: skip,
+		from: fmt.Sprintf("XDG base dir"),
+		apply: func(baseConfig interface{}) error {
+			if err != nil {
+				return err
+			}
+			return FromTOMLFile(configFile, baseConfig)
+		},
+	}
+}
+
+// Source from a single environment variable with config embedded in JSON
+func Environment(key string) *configSource {
+	jsonString := os.Getenv(key)
+	return &configSource{
+		skip: jsonString == "",
+		from: fmt.Sprintf("'%s' environment variable (as JSON)", key),
+		apply: func(baseConfig interface{}) error {
+			return FromJSONString(jsonString, baseConfig)
+		},
+	}
+}
+
+func Default(defaultConfig interface{}) *configSource {
+	return &configSource{
+		from: "defaults",
+		apply: func(baseConfig interface{}) error {
+			return mergo.MergeWithOverwrite(baseConfig, defaultConfig)
+		},
+	}
+}
+
+func FromJSONFile(configFile string, conf interface{}) error {
+	bs, err := ReadFile(configFile)
+	if err != nil {
+		return err
+	}
+
+	return FromJSONString(string(bs), conf)
+}
+
+func FromTOMLFile(configFile string, conf interface{}) error {
+	bs, err := ReadFile(configFile)
+	if err != nil {
+		return err
+	}
+
+	return FromTOMLString(string(bs), conf)
+}
+
+func FromTOMLString(tomlString string, conf interface{}) error {
+	_, err := toml.Decode(tomlString, conf)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func FromJSONString(jsonString string, conf interface{}) error {
+	err := json.Unmarshal(([]byte)(jsonString), conf)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func TOMLString(conf interface{}) string {
+	buf := new(bytes.Buffer)
+	encoder := toml.NewEncoder(buf)
+	err := encoder.Encode(conf)
+	if err != nil {
+		return fmt.Sprintf("<Could not serialise config: %v>", err)
+	}
+	return buf.String()
+}
+
+func JSONString(conf interface{}) string {
+	bs, err := json.MarshalIndent(conf, "", "\t")
+	if err != nil {
+		return fmt.Sprintf("<Could not serialise config: %v>", err)
+	}
+	return string(bs)
+}
+
+func Merge(base, override interface{}) (interface{}, error) {
+	merged, err := DeepCopy(base)
+	if err != nil {
+		return nil, err
+	}
+	err = mergo.MergeWithOverwrite(merged, override)
+	if err != nil {
+		return nil, err
+	}
+	return merged, nil
+}
+
+// Passed a pointer to struct creates a deep copy of the struct
+func DeepCopy(conf interface{}) (interface{}, error) {
+	// Create a zero value
+	confCopy := reflect.New(reflect.TypeOf(conf).Elem()).Interface()
+	// Perform a merge into that value to effect the copy
+	err := mergo.Merge(confCopy, conf)
+	if err != nil {
+		return nil, err
+	}
+	return confCopy, nil
+}
+
+func writeLog(writer io.Writer, msg string) {
+	if writer != nil {
+		writer.Write(([]byte)(msg))
+		writer.Write(([]byte)("\n"))
+	}
+}
+
+func ReadFile(file string) ([]byte, error) {
+	if file == STDINFileIdentifier {
+		return ioutil.ReadAll(os.Stdin)
+	}
+	return ioutil.ReadFile(file)
+}
+
+func ShouldSkipFile(file string, skipNonExistent bool) bool {
+	skip := file == ""
+	if !skip && skipNonExistent {
+		_, err := os.Stat(file)
+		skip = os.IsNotExist(err)
+	}
+	return skip
+}
diff --git a/config/source/source_test.go b/config/source/source_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..7bf062b40dd6e1713725eb74da0177ce1d2ea861
--- /dev/null
+++ b/config/source/source_test.go
@@ -0,0 +1,111 @@
+package source
+
+import (
+	"io/ioutil"
+	"os"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+func TestEnvironment(t *testing.T) {
+	envVar := "FISH_SPOON_ALPHA"
+	jsonString := JSONString(newTestConfig())
+	os.Setenv(envVar, jsonString)
+	conf := new(animalConfig)
+	err := Environment(envVar).Apply(conf)
+	assert.NoError(t, err)
+	assert.Equal(t, jsonString, JSONString(conf))
+}
+
+func TestDeepCopy(t *testing.T) {
+	conf := newTestConfig()
+	confCopy, err := DeepCopy(conf)
+	require.NoError(t, err)
+	assert.Equal(t, conf, confCopy)
+}
+
+func TestFile(t *testing.T) {
+	tomlString := TOMLString(newTestConfig())
+	file := writeConfigFile(t, newTestConfig())
+	defer os.Remove(file)
+	conf := new(animalConfig)
+	err := TOMLFile(file, false).Apply(conf)
+	assert.NoError(t, err)
+	assert.Equal(t, tomlString, TOMLString(conf))
+}
+
+func TestCascade(t *testing.T) {
+	envVar := "FISH_SPOON_ALPHA"
+	// Both fall through so baseConfig returned
+	conf := newTestConfig()
+	err := Cascade(os.Stderr, true,
+		Environment(envVar),
+		TOMLFile("", false)).Apply(conf)
+	assert.NoError(t, err)
+	assert.Equal(t, newTestConfig(), conf)
+
+	// Env not set so falls through to file
+	fileConfig := newTestConfig()
+	file := writeConfigFile(t, fileConfig)
+	defer os.Remove(file)
+	conf = new(animalConfig)
+	err = Cascade(os.Stderr, true,
+		Environment(envVar),
+		TOMLFile(file, false)).Apply(conf)
+	assert.NoError(t, err)
+	assert.Equal(t, TOMLString(fileConfig), TOMLString(conf))
+
+	// Env set so caught by environment source
+	envConfig := animalConfig{
+		Name:    "Slug",
+		NumLegs: 0,
+	}
+	os.Setenv(envVar, JSONString(envConfig))
+	conf = newTestConfig()
+	err = Cascade(os.Stderr, true,
+		Environment(envVar),
+		TOMLFile(file, false)).Apply(conf)
+	assert.NoError(t, err)
+	assert.Equal(t, TOMLString(envConfig), TOMLString(conf))
+}
+
+func writeConfigFile(t *testing.T, conf interface{}) string {
+	tomlString := TOMLString(conf)
+	f, err := ioutil.TempFile("", "source-test.toml")
+	assert.NoError(t, err)
+	f.Write(([]byte)(tomlString))
+	f.Close()
+	return f.Name()
+}
+
+// Test types
+
+type legConfig struct {
+	Leg    int
+	Colour byte
+}
+
+type animalConfig struct {
+	Name    string
+	NumLegs int
+	Legs    []legConfig
+}
+
+func newTestConfig() *animalConfig {
+	return &animalConfig{
+		Name:    "Froggy!",
+		NumLegs: 2,
+		Legs: []legConfig{
+			{
+				Leg:    1,
+				Colour: 034,
+			},
+			{
+				Leg:    2,
+				Colour: 034,
+			},
+		},
+	}
+}
diff --git a/core/config.go b/core/config.go
deleted file mode 100644
index bddb21b8491f69ed719230ceba412aa2c34aa028..0000000000000000000000000000000000000000
--- a/core/config.go
+++ /dev/null
@@ -1,120 +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.
-
-// config.go keeps explicit structures on the runtime configuration of
-// burrow and all modules.  It loads these from the Viper configuration
-// loaded in `definitions.Do`
-
-package core
-
-import (
-	"fmt"
-	"os"
-	"path"
-
-	"github.com/hyperledger/burrow/config"
-	"github.com/hyperledger/burrow/definitions"
-	lconfig "github.com/hyperledger/burrow/logging/config"
-	"github.com/hyperledger/burrow/server"
-	"github.com/hyperledger/burrow/util"
-	"github.com/spf13/viper"
-)
-
-// LoadConsensusModuleConfig wraps specifically for the consensus module
-func LoadConsensusModuleConfig(do *definitions.Do) (*config.ModuleConfig, error) {
-	return loadModuleConfigFromDo(do, "consensus")
-}
-
-// LoadApplicationManagerModuleConfig wraps specifically for the application
-// manager
-func LoadApplicationManagerModuleConfig(do *definitions.Do) (*config.ModuleConfig, error) {
-	return loadModuleConfigFromDo(do, "manager")
-}
-
-func loadModuleConfigFromDo(do *definitions.Do, module string) (*config.ModuleConfig, error) {
-	return LoadModuleConfig(do.Config, do.WorkDir, do.DataDir,
-		do.GenesisFile, do.ChainId, module)
-}
-
-// Generic Module loader for configuration information
-func LoadModuleConfig(conf *viper.Viper, rootWorkDir, rootDataDir,
-	genesisFile, chainId, module string) (*config.ModuleConfig, error) {
-	moduleName := conf.GetString("chain." + module + ".name")
-	// set up the directory structure for the module inside the data directory
-	workDir := path.Join(rootDataDir, conf.GetString("chain."+module+
-		".relative_root"))
-	if err := util.EnsureDir(workDir, os.ModePerm); err != nil {
-		return nil,
-			fmt.Errorf("Failed to create module root directory %s.", workDir)
-	}
-	dataDir := path.Join(workDir, "data")
-	if err := util.EnsureDir(dataDir, os.ModePerm); err != nil {
-		return nil,
-			fmt.Errorf("Failed to create module data directory %s.", dataDir)
-	}
-	// load configuration subtree for module
-	if !conf.IsSet(moduleName) {
-		return nil, fmt.Errorf("Failed to read configuration section for %s",
-			moduleName)
-	}
-	subConfig, err := config.ViperSubConfig(conf, moduleName)
-	if subConfig == nil {
-		return nil, fmt.Errorf("Failed to read configuration section for %s: %s",
-			moduleName, err)
-	}
-
-	return &config.ModuleConfig{
-		Module:      module,
-		Name:        moduleName,
-		WorkDir:     workDir,
-		DataDir:     dataDir,
-		RootDir:     rootWorkDir, // burrow's working directory
-		ChainId:     chainId,
-		GenesisFile: genesisFile,
-		Config:      subConfig,
-	}, nil
-}
-
-// Load the ServerConfig from commandline Do object
-func LoadServerConfigFromDo(do *definitions.Do) (*server.ServerConfig, error) {
-	// load configuration subtree for servers
-	return LoadServerConfig(do.ChainId, do.Config)
-}
-
-// Load the ServerConfig from root Viper config, fixing the ChainId
-func LoadServerConfig(chainId string, rootConfig *viper.Viper) (*server.ServerConfig, error) {
-	subConfig, err := config.ViperSubConfig(rootConfig, "servers")
-	if err != nil {
-		return nil, err
-	}
-	serverConfig, err := server.ReadServerConfig(subConfig)
-	if err != nil {
-		return nil, err
-	}
-	serverConfig.ChainId = chainId
-	return serverConfig, err
-}
-
-func LoadLoggingConfigFromDo(do *definitions.Do) (*lconfig.LoggingConfig, error) {
-	if !do.Config.IsSet("logging") {
-		return nil, nil
-	}
-	loggingConfigMap := do.Config.GetStringMap("logging")
-	return lconfig.LoggingConfigFromMap(loggingConfigMap)
-}
-
-func LoadLoggingConfigFromClientDo(do *definitions.ClientDo) (*lconfig.LoggingConfig, error) {
-	loggingConfig := lconfig.DefaultClientLoggingConfig()
-	return loggingConfig, nil
-}
diff --git a/core/config_test.go b/core/config_test.go
deleted file mode 100644
index ef552d2b0581d48538e6119a2b5615474fe05de4..0000000000000000000000000000000000000000
--- a/core/config_test.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package core
-
-import (
-	"testing"
-
-	"github.com/hyperledger/burrow/config"
-	"github.com/hyperledger/burrow/definitions"
-	lconfig "github.com/hyperledger/burrow/logging/config"
-	"github.com/spf13/viper"
-	"github.com/stretchr/testify/assert"
-)
-
-func TestLoadLoggingConfigFromDo(t *testing.T) {
-	do := new(definitions.Do)
-	do.Config = viper.New()
-	lc, err := LoadLoggingConfigFromDo(do)
-	assert.NoError(t, err)
-	assert.Nil(t, lc, "Should get nil logging config when [logging] not set")
-	cnf, err := config.ReadViperConfig(([]byte)(lconfig.DefaultNodeLoggingConfig().RootTOMLString()))
-	assert.NoError(t, err)
-	do.Config = cnf
-	lc, err = LoadLoggingConfigFromDo(do)
-	assert.NoError(t, err)
-	assert.EqualValues(t, lconfig.DefaultNodeLoggingConfig(), lc)
-}
diff --git a/core/core.go b/core/core.go
deleted file mode 100644
index 3727a823203850afe0881b950ebb41b6a10ec253..0000000000000000000000000000000000000000
--- a/core/core.go
+++ /dev/null
@@ -1,125 +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 core
-
-import (
-	"fmt"
-
-	// TODO: [ben] swap out go-events with burrow/event (currently unused)
-	events "github.com/tendermint/go-events"
-
-	"github.com/hyperledger/burrow/config"
-	"github.com/hyperledger/burrow/consensus"
-	"github.com/hyperledger/burrow/definitions"
-	"github.com/hyperledger/burrow/event"
-	"github.com/hyperledger/burrow/manager"
-	// rpc_v0 is carried over from burrowv0.11 and before on port 1337
-	rpc_v0 "github.com/hyperledger/burrow/rpc/v0"
-	// rpc_tendermint is carried over from burrowv0.11 and before on port 46657
-
-	"github.com/hyperledger/burrow/logging"
-	logging_types "github.com/hyperledger/burrow/logging/types"
-	rpc_tendermint "github.com/hyperledger/burrow/rpc/tendermint/core"
-	"github.com/hyperledger/burrow/server"
-)
-
-// Core is the high-level structure
-type Core struct {
-	chainId        string
-	evsw           events.EventSwitch
-	pipe           definitions.Pipe
-	tendermintPipe definitions.TendermintPipe
-	logger         logging_types.InfoTraceLogger
-}
-
-func NewCore(chainId string,
-	consensusConfig *config.ModuleConfig,
-	managerConfig *config.ModuleConfig,
-	logger logging_types.InfoTraceLogger) (*Core, error) {
-	// start new event switch, TODO: [ben] replace with burrow/event
-	evsw := events.NewEventSwitch()
-	evsw.Start()
-	logger = logging.WithScope(logger, "Core")
-
-	// start a new application pipe that will load an application manager
-	pipe, err := manager.NewApplicationPipe(managerConfig, evsw, logger)
-	if err != nil {
-		return nil, fmt.Errorf("Failed to load application pipe: %v", err)
-	}
-	logging.TraceMsg(logger, "Loaded pipe with application manager")
-	// pass the consensus engine into the pipe
-	if e := consensus.LoadConsensusEngineInPipe(consensusConfig, pipe); e != nil {
-		return nil, fmt.Errorf("Failed to load consensus engine in pipe: %v", e)
-	}
-	tendermintPipe, err := pipe.GetTendermintPipe()
-	if err != nil {
-		logging.TraceMsg(logger, "Tendermint gateway not supported by manager",
-			"manager", managerConfig.Name)
-	}
-	return &Core{
-		chainId:        chainId,
-		evsw:           evsw,
-		pipe:           pipe,
-		tendermintPipe: tendermintPipe,
-		logger:         logger,
-	}, nil
-}
-
-//------------------------------------------------------------------------------
-// Explicit switch that can later be abstracted into an `Engine` definition
-// where the Engine defines the explicit interaction of a specific application
-// manager with a consensus engine.
-// TODO: [ben] before such Engine abstraction,
-// think about many-manager-to-one-consensus
-
-//------------------------------------------------------------------------------
-// Server functions
-// NOTE: [ben] in phase 0 we exactly take over the full server architecture
-// from burrow and Tendermint; This is a draft and will be overhauled.
-
-func (core *Core) NewGatewayV0(config *server.ServerConfig) (*server.ServeProcess,
-	error) {
-	codec := &rpc_v0.TCodec{}
-	eventSubscriptions := event.NewEventSubscriptions(core.pipe.Events())
-	// The services.
-	tmwss := rpc_v0.NewBurrowWsService(codec, core.pipe)
-	tmjs := rpc_v0.NewBurrowJsonService(codec, core.pipe, eventSubscriptions)
-	// The servers.
-	jsonServer := rpc_v0.NewJsonRpcServer(tmjs)
-	restServer := rpc_v0.NewRestServer(codec, core.pipe, eventSubscriptions)
-	wsServer := server.NewWebSocketServer(config.WebSocket.MaxWebSocketSessions,
-		tmwss, core.logger)
-	// Create a server process.
-	proc, err := server.NewServeProcess(config, core.logger, jsonServer, restServer, wsServer)
-	if err != nil {
-		return nil, fmt.Errorf("Failed to load gateway: %v", err)
-	}
-
-	return proc, nil
-}
-
-func (core *Core) NewGatewayTendermint(config *server.ServerConfig) (
-	*rpc_tendermint.TendermintWebsocketServer, error) {
-	if core.tendermintPipe == nil {
-		return nil, fmt.Errorf("No Tendermint pipe has been initialised for Tendermint gateway.")
-	}
-	return rpc_tendermint.NewTendermintWebsocketServer(config,
-		core.tendermintPipe, core.evsw)
-}
-
-// Stop the core allowing for a graceful shutdown of component in order.
-func (core *Core) Stop() bool {
-	return core.pipe.GetConsensusEngine().Stop()
-}
diff --git a/core/kernel.go b/core/kernel.go
new file mode 100644
index 0000000000000000000000000000000000000000..81ddfce577ae1552775b3deadbe143d83bd72a7a
--- /dev/null
+++ b/core/kernel.go
@@ -0,0 +1,166 @@
+// 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 core
+
+import (
+	"net"
+	"os"
+	"os/signal"
+	"sync"
+
+	"fmt"
+
+	bcm "github.com/hyperledger/burrow/blockchain"
+	"github.com/hyperledger/burrow/consensus/tendermint"
+	"github.com/hyperledger/burrow/consensus/tendermint/query"
+	"github.com/hyperledger/burrow/event"
+	"github.com/hyperledger/burrow/execution"
+	"github.com/hyperledger/burrow/genesis"
+	"github.com/hyperledger/burrow/logging"
+	logging_types "github.com/hyperledger/burrow/logging/types"
+	"github.com/hyperledger/burrow/rpc"
+	"github.com/hyperledger/burrow/rpc/tm"
+	"github.com/hyperledger/burrow/txs"
+	tm_config "github.com/tendermint/tendermint/config"
+	"github.com/tendermint/tendermint/node"
+	tm_types "github.com/tendermint/tendermint/types"
+	dbm "github.com/tendermint/tmlibs/db"
+	"github.com/tendermint/tmlibs/events"
+)
+
+// Kernel is the root structure of Burrow
+type Kernel struct {
+	eventSwitch     events.EventSwitch
+	tmNode          *node.Node
+	service         rpc.Service
+	serverLaunchers []ServerLauncher
+	listeners       []net.Listener
+	logger          logging_types.InfoTraceLogger
+	shutdownNotify  chan struct{}
+	shutdownOnce    sync.Once
+}
+
+type ServerLauncher struct {
+	Name   string
+	Launch func(rpc.Service) (net.Listener, error)
+}
+
+func NewKernel(privValidator tm_types.PrivValidator, genesisDoc *genesis.GenesisDoc, tmConf *tm_config.Config,
+	rpcConfig *rpc.RPCConfig, logger logging_types.InfoTraceLogger) (*Kernel, error) {
+
+	events.NewEventSwitch().Start()
+	logger = logging.WithScope(logger, "NewKernel")
+
+	stateDB := dbm.NewDB("burrow_state", dbm.GoLevelDBBackendStr, tmConf.DBDir())
+	state := execution.MakeGenesisState(stateDB, genesisDoc)
+	state.Save()
+
+	blockchain := bcm.NewBlockchain(genesisDoc)
+	evmEvents := event.NewEmitter(logger)
+
+	tmGenesisDoc := tendermint.DeriveGenesisDoc(genesisDoc)
+	checker := execution.NewBatchChecker(state, tmGenesisDoc.ChainID, blockchain, logger)
+	committer := execution.NewBatchCommitter(state, tmGenesisDoc.ChainID, blockchain, evmEvents, logger)
+	tmNode, err := tendermint.NewNode(tmConf, privValidator, tmGenesisDoc, blockchain, checker, committer, logger)
+	if err != nil {
+		return nil, err
+	}
+	// Multiplex Tendermint and EVM events
+	eventEmitter := event.Multiplex(evmEvents, event.WrapEventSwitch(tmNode.EventSwitch(), logger))
+
+	txCodec := txs.NewGoWireCodec()
+	nameReg := execution.NewNameReg(state, blockchain)
+
+	transactor := execution.NewTransactor(blockchain, state, eventEmitter,
+		tendermint.BroadcastTxAsyncFunc(tmNode, txCodec), logger)
+
+	// TODO: consider whether we need to be more explicit about pre-commit (check cache) versus committed (state) values
+	// Note we pass the checker as the StateIterable to NewService which means the RPC layers will query the check
+	// cache state. This is in line with previous behaviour of Burrow and chiefly serves to get provide a pre-commit
+	// view of nonce values on the node that a client is communicating with.
+	// Since we don't currently execute EVM code in the checker possible conflicts are limited to account creation
+	// which increments the creator's account Sequence and SendTxs
+	service := rpc.NewService(state, eventEmitter, nameReg, blockchain, transactor, query.NewNodeView(tmNode, txCodec),
+		logger)
+
+	servers := []ServerLauncher{
+		{
+			Name: "TM",
+			Launch: func(service rpc.Service) (net.Listener, error) {
+				return tm.StartServer(service, "/websocket", rpcConfig.TM.ListenAddress, eventEmitter, logger)
+			},
+		},
+	}
+
+	return &Kernel{
+		eventSwitch:     eventEmitter,
+		tmNode:          tmNode,
+		service:         service,
+		serverLaunchers: servers,
+		logger:          logger,
+		shutdownNotify:  make(chan struct{}),
+	}, nil
+}
+
+// Boot the kernel starting Tendermint and RPC layers
+func (kern *Kernel) Boot() error {
+	_, err := kern.tmNode.Start()
+	if err != nil {
+		return fmt.Errorf("error starting Tendermint node: %v", err)
+	}
+	for _, launcher := range kern.serverLaunchers {
+		listener, err := launcher.Launch(kern.service)
+		if err != nil {
+			return fmt.Errorf("error launching %s server", launcher.Name)
+		}
+
+		kern.listeners = append(kern.listeners, listener)
+	}
+	go kern.supervise()
+	return nil
+}
+
+// Wait for a graceful shutdown
+func (kern *Kernel) WaitForShutdown() {
+	// Supports multiple goroutines waiting for shutdown since channel is closed
+	<-kern.shutdownNotify
+}
+
+// Supervise kernel once booted
+func (kern *Kernel) supervise() {
+	// TODO: Consider capturing kernel panics from boot and sending them here via a channel where we could
+	// perform disaster restarts of the kernel; rejoining the network as if we were a new node.
+	signals := make(chan os.Signal, 1)
+	signal.Notify(signals, os.Interrupt, os.Kill)
+	<-signals
+	kern.Shutdown()
+}
+
+// Stop the kernel allowing for a graceful shutdown of components in order
+func (kern *Kernel) Shutdown() (err error) {
+	kern.shutdownOnce.Do(func() {
+		logger := logging.WithScope(kern.logger, "Shutdown")
+		logging.InfoMsg(logger, "Attempting graceful shutdown...")
+		logging.InfoMsg(logger, "Shutting down listeners")
+		for _, listener := range kern.listeners {
+			err = listener.Close()
+		}
+		logging.InfoMsg(logger, "Shutting down Tendermint node")
+		kern.tmNode.Stop()
+		logging.InfoMsg(logger, "Shutdown complete")
+		close(kern.shutdownNotify)
+	})
+	return
+}
diff --git a/core/kernel_test.go b/core/kernel_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..857d739924681afdbc3a83fe0fd16410f4b305f7
--- /dev/null
+++ b/core/kernel_test.go
@@ -0,0 +1,33 @@
+package core
+
+import (
+	"os"
+	"testing"
+
+	"github.com/hyperledger/burrow/consensus/tendermint/validator"
+	"github.com/hyperledger/burrow/genesis"
+	"github.com/hyperledger/burrow/logging/loggers"
+	"github.com/hyperledger/burrow/rpc"
+	"github.com/stretchr/testify/require"
+	tm_config "github.com/tendermint/tendermint/config"
+)
+
+const testDir = "./test_scratch/kernel_test"
+
+func TestBootThenShutdown(t *testing.T) {
+
+	os.RemoveAll(testDir)
+	os.MkdirAll(testDir, 0777)
+	os.Chdir(testDir)
+	tmConf := tm_config.DefaultConfig()
+	//logger, _ := lifecycle.NewStdErrLogger()
+	logger := loggers.NewNoopInfoTraceLogger()
+	genesisDoc, privateAccounts := genesis.NewDeterministicGenesis(123).GenesisDoc(1, true, 1000, 1, true, 1000)
+	privValidator := validator.NewPrivValidatorMemory(privateAccounts[0], privateAccounts[0])
+	kern, err := NewKernel(privValidator, genesisDoc, tmConf, rpc.DefaultRPCConfig(), logger)
+	require.NoError(t, err)
+	err = kern.Boot()
+	require.NoError(t, err)
+	err = kern.Shutdown()
+	require.NoError(t, err)
+}
diff --git a/core/types/types.go b/core/types/types.go
index 5b0934c164e3b90cf3245578ab0c70d6c76dbf9b..220b9e3742c547d5446bbee9036c643fc947e1f9 100644
--- a/core/types/types.go
+++ b/core/types/types.go
@@ -14,45 +14,19 @@
 
 package types
 
-// TODO: [ben] this is poorly constructed but copied over
-// from burrow/burrow/pipe/types to make incremental changes and allow
-// for a discussion around the proper defintion of the needed types.
-
 import (
-	// NodeInfo (drop this!)
-	"github.com/tendermint/tendermint/types"
-
-	account "github.com/hyperledger/burrow/account"
+	tm_types "github.com/tendermint/tendermint/types"
 )
 
 type (
-	// *********************************** Address ***********************************
-
-	// Accounts
-	AccountList struct {
-		Accounts []*account.Account `json:"accounts"`
-	}
-
-	// A contract account storage item.
-	StorageItem struct {
-		Key   []byte `json:"key"`
-		Value []byte `json:"value"`
-	}
-
-	// Account storage
-	Storage struct {
-		StorageRoot  []byte        `json:"storage_root"`
-		StorageItems []StorageItem `json:"storage_items"`
-	}
-
 	// *********************************** Blockchain ***********************************
 
 	// BlockchainInfo
 	BlockchainInfo struct {
-		ChainId           string           `json:"chain_id"`
-		GenesisHash       []byte           `json:"genesis_hash"`
-		LatestBlockHeight int              `json:"latest_block_height"`
-		LatestBlock       *types.BlockMeta `json:"latest_block"`
+		ChainId           string              `json:"chain_id"`
+		GenesisHash       []byte              `json:"genesis_hash"`
+		LatestBlockHeight uint64              `json:"latest_block_height"`
+		LatestBlock       *tm_types.BlockMeta `json:"latest_block"`
 	}
 
 	// Genesis hash
@@ -62,7 +36,7 @@ type (
 
 	// Get the latest
 	LatestBlockHeight struct {
-		Height int `json:"height"`
+		Height uint64 `json:"height"`
 	}
 
 	ChainId struct {
@@ -71,78 +45,17 @@ type (
 
 	// GetBlocks
 	Blocks struct {
-		MinHeight  int                `json:"min_height"`
-		MaxHeight  int                `json:"max_height"`
-		BlockMetas []*types.BlockMeta `json:"block_metas"`
+		MinHeight  uint64                `json:"min_height"`
+		MaxHeight  uint64                `json:"max_height"`
+		BlockMetas []*tm_types.BlockMeta `json:"block_metas"`
 	}
 
 	// *********************************** Consensus ***********************************
 
 	// Validators
 	ValidatorList struct {
-		BlockHeight         int                `json:"block_height"`
-		BondedValidators    []*types.Validator `json:"bonded_validators"`
-		UnbondingValidators []*types.Validator `json:"unbonding_validators"`
-	}
-
-	// *********************************** Events ***********************************
-
-	// EventSubscribe
-	EventSub struct {
-		SubId string `json:"sub_id"`
-	}
-
-	// EventUnsubscribe
-	EventUnsub struct {
-		Result bool `json:"result"`
-	}
-
-	// EventPoll
-	PollResponse struct {
-		Events []interface{} `json:"events"`
-	}
-
-	// *********************************** Network ***********************************
-
-	ClientVersion struct {
-		ClientVersion string `json:"client_version"`
-	}
-
-	Moniker struct {
-		Moniker string `json:"moniker"`
-	}
-
-	Listening struct {
-		Listening bool `json:"listening"`
-	}
-
-	Listeners struct {
-		Listeners []string `json:"listeners"`
-	}
-
-	// *********************************** Transactions ***********************************
-
-	// Call or CallCode
-	Call struct {
-		Return  string `json:"return"`
-		GasUsed int64  `json:"gas_used"`
-		// TODO ...
-	}
-)
-
-//------------------------------------------------------------------------------
-// copied in from NameReg
-
-type (
-	NameRegEntry struct {
-		Name    string `json:"name"`    // registered name for the entry
-		Owner   []byte `json:"owner"`   // address that created the entry
-		Data    string `json:"data"`    // data to store under this name
-		Expires int    `json:"expires"` // block at which this entry expires
-	}
-
-	ResultListNames struct {
-		BlockHeight int             `json:"block_height"`
-		Names       []*NameRegEntry `json:"names"`
+		BlockHeight         uint64                `json:"block_height"`
+		BondedValidators    []*tm_types.Validator `json:"bonded_validators"`
+		UnbondingValidators []*tm_types.Validator `json:"unbonding_validators"`
 	}
 )