diff --git a/blockchain/blockchain.go b/blockchain/blockchain.go
index 98e48b14a237d2c37a3a2035e42d369521ef237f..af8e43e413f415f74a319641e667d22c10c9d555 100644
--- a/blockchain/blockchain.go
+++ b/blockchain/blockchain.go
@@ -148,11 +148,18 @@ func NewTip(chainID string, genesisTime time.Time, genesisHash []byte) *Tip {
 func (bc *Blockchain) CommitBlock(blockTime time.Time, blockHash, appHash []byte) error {
 	bc.Lock()
 	defer bc.Unlock()
+	// Checkpoint on the _previous_ block. If we die, this is where we will resume since we know it must have been
+	// committed since we are committing the next block. If we fall over we can resume a safe committed state and
+	// Tendermint will catch us up
+	err := bc.save()
+	if err != nil {
+		return err
+	}
 	bc.lastBlockHeight += 1
 	bc.lastBlockTime = blockTime
 	bc.lastBlockHash = blockHash
 	bc.appHashAfterLastBlock = appHash
-	return bc.save()
+	return nil
 }
 
 func (bc *Blockchain) save() error {
diff --git a/consensus/tendermint/abci/app.go b/consensus/tendermint/abci/app.go
index 6cca22aef6580d1feeeb653adb3516be3a3827b9..ba7fec9f55324e640ec2f24b0ccf6a440f5c97b9 100644
--- a/consensus/tendermint/abci/app.go
+++ b/consensus/tendermint/abci/app.go
@@ -227,13 +227,15 @@ func (app *App) Commit() abciTypes.ResponseCommit {
 		}
 	}()
 
+	// First commit the app start, this app hash will not get checkpointed until the next block when we are sure
+	// that nothing in the downstream commit process could have failed. At worst we go back one block.
 	appHash, err := app.committer.Commit()
 	if err != nil {
 		panic(errors.Wrap(err, "Could not commit transactions in block to execution state"))
-
 	}
 
-	// Commit to our blockchain state
+	// Commit to our blockchain state which will checkpoint the previous app hash by saving it to the database
+	// (we know the previous app hash is safely committed because we are about to commit the next)
 	err = app.blockchain.CommitBlock(time.Unix(int64(app.block.Header.Time), 0), app.block.Hash, appHash)
 	if err != nil {
 		panic(errors.Wrap(err, "could not commit block to blockchain state"))
diff --git a/consensus/tendermint/tendermint.go b/consensus/tendermint/tendermint.go
index 175cbab85273ca972dbc4434d0e8ef6b51f63f75..8e9813f48a7a22fd35338708efc211c0138ea55a 100644
--- a/consensus/tendermint/tendermint.go
+++ b/consensus/tendermint/tendermint.go
@@ -90,10 +90,11 @@ func DeriveGenesisDoc(burrowGenesisDoc *genesis.GenesisDoc) *tm_types.GenesisDoc
 		}
 	}
 	return &tm_types.GenesisDoc{
-		ChainID:     burrowGenesisDoc.ChainID(),
-		GenesisTime: burrowGenesisDoc.GenesisTime,
-		Validators:  validators,
-		AppHash:     burrowGenesisDoc.Hash(),
+		ChainID:         burrowGenesisDoc.ChainID(),
+		GenesisTime:     burrowGenesisDoc.GenesisTime,
+		Validators:      validators,
+		AppHash:         burrowGenesisDoc.Hash(),
+		ConsensusParams: tm_types.DefaultConsensusParams(),
 	}
 }
 
diff --git a/core/kernel.go b/core/kernel.go
index f5a8549f56ffbc666be97488b08938b34ed69738..a92a5b3ace13480cef033abe13c59fbe571a39a2 100644
--- a/core/kernel.go
+++ b/core/kernel.go
@@ -84,7 +84,7 @@ func NewKernel(ctx context.Context, keyClient keys.KeyClient, privValidator tm_t
 	var state *execution.State
 	// These should be in sync unless we are at the genesis block
 	if blockchain.LastBlockHeight() > 0 {
-		state, err = execution.LoadState(stateDB)
+		state, err = execution.LoadState(stateDB, blockchain.AppHashAfterLastBlock())
 		if err != nil {
 			return nil, fmt.Errorf("could not load persisted execution state at hash 0x%X: %v",
 				blockchain.AppHashAfterLastBlock(), err)
diff --git a/core/kernel_test.go b/core/kernel_test.go
index d242de8e9946a882c68cd54e894a156168248754..fae573639b9ce3c39eb379e187447bac2fd9e47b 100644
--- a/core/kernel_test.go
+++ b/core/kernel_test.go
@@ -14,6 +14,7 @@ import (
 	"github.com/hyperledger/burrow/logging"
 	"github.com/hyperledger/burrow/rpc"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 	tmConfig "github.com/tendermint/tendermint/config"
 	tmTypes "github.com/tendermint/tendermint/types"
 )
@@ -42,18 +43,18 @@ func TestBootShutdownResume(t *testing.T) {
 	genesisDoc, _, privateValidators := genesis.NewDeterministicGenesis(123).GenesisDoc(1, true, 1000, 1, true, 1000)
 	privValidator := validator.NewPrivValidatorMemory(privateValidators[0], privateValidators[0])
 
-	i := int64(1)
+	i := int64(0)
 	// asserts we get a consecutive run of blocks
 	blockChecker := func(block *tmTypes.EventDataNewBlock) bool {
-		assert.Equal(t, i, block.Block.Height)
+		assert.Equal(t, i+1, block.Block.Height)
 		i++
 		// stop every third block
 		return i%3 != 0
 	}
 	// First run
-	assert.NoError(t, bootWaitBlocksShutdown(privValidator, genesisDoc, tmConf, logger, blockChecker))
+	require.NoError(t, bootWaitBlocksShutdown(privValidator, genesisDoc, tmConf, logger, blockChecker))
 	// Resume and check we pick up where we left off
-	assert.NoError(t, bootWaitBlocksShutdown(privValidator, genesisDoc, tmConf, logger, blockChecker))
+	require.NoError(t, bootWaitBlocksShutdown(privValidator, genesisDoc, tmConf, logger, blockChecker))
 	// Resuming with mismatched genesis should fail
 	genesisDoc.Salt = []byte("foo")
 	assert.Error(t, bootWaitBlocksShutdown(privValidator, genesisDoc, tmConf, logger, blockChecker))
diff --git a/execution/state.go b/execution/state.go
index b4b03ce91b2405399ac69ebb97e24ec2be48bd9a..39942cda25ffea3cf263a964f521b18b3910a086 100644
--- a/execution/state.go
+++ b/execution/state.go
@@ -57,8 +57,7 @@ var _ state.Writer = &State{}
 
 type State struct {
 	sync.RWMutex
-	db dbm.DB
-	// TODO:
+	db     dbm.DB
 	tree   *iavl.VersionedTree
 	logger *logging.Logger
 }
@@ -129,25 +128,53 @@ func MakeGenesisState(db dbm.DB, genesisDoc *genesis.GenesisDoc) (*State, error)
 }
 
 // Tries to load the execution state from DB, returns nil with no error if no state found
-func LoadState(db dbm.DB) (*State, error) {
+func LoadState(db dbm.DB, hash []byte) (*State, error) {
 	s := NewState(db)
-	_, err := s.tree.Load()
+	// Get the version associated with this state hash
+	version, err := s.GetVersion(hash)
+	if err != nil {
+		return nil, err
+	}
+	treeVersion, err := s.tree.LoadVersion(version)
 	if err != nil {
 		return nil, fmt.Errorf("could not load versioned state tree")
 	}
+	if treeVersion != version {
+		return nil, fmt.Errorf("tried to load state version %v for state hash %X but loaded version %v",
+			version, hash, treeVersion)
+	}
 	return s, nil
 }
 
 func (s *State) Save() error {
 	s.Lock()
 	defer s.Unlock()
-	_, _, err := s.tree.SaveVersion()
+	// Save state at a new version may still be orphaned before we save the version against the hash
+	hash, treeVersion, err := s.tree.SaveVersion()
 	if err != nil {
 		return err
 	}
+	// Provide a reference to load this version in the future from the state hash
+	s.SetVersion(hash, treeVersion)
 	return nil
 }
 
+// Get a previously saved tree version stored by state hash
+func (s *State) GetVersion(hash []byte) (int64, error) {
+	versionBytes := s.db.Get(prefixedKey(versionPrefix, hash))
+	if versionBytes == nil {
+		return -1, fmt.Errorf("could not retrieve version corresponding to state hash '%X' in database", hash)
+	}
+	return binary.GetInt64BE(versionBytes), nil
+}
+
+// Set the tree version associated with a particular hash
+func (s *State) SetVersion(hash []byte, version int64) {
+	versionBytes := make([]byte, 8)
+	binary.PutInt64BE(versionBytes, version)
+	s.db.SetSync(prefixedKey(versionPrefix, hash), versionBytes)
+}
+
 // Computes the state hash, also computed on save where it is returned
 func (s *State) Hash() []byte {
 	s.RLock()