diff --git a/cmd/ethereum/blocktest.go b/cmd/ethereum/blocktest.go
new file mode 100644
index 0000000000000000000000000000000000000000..1bb3809cf2af715d353089c221887c351c94b7d0
--- /dev/null
+++ b/cmd/ethereum/blocktest.go
@@ -0,0 +1,66 @@
+package main
+
+import (
+	"fmt"
+
+	"github.com/codegangsta/cli"
+	"github.com/ethereum/go-ethereum/cmd/utils"
+	"github.com/ethereum/go-ethereum/eth"
+	"github.com/ethereum/go-ethereum/ethdb"
+	"github.com/ethereum/go-ethereum/ethutil"
+	"github.com/ethereum/go-ethereum/tests"
+)
+
+var blocktestCmd = cli.Command{
+	Action: runblocktest,
+	Name:   "blocktest",
+	Usage:  `loads a block test file`,
+	Description: `
+The first argument should be a block test file.
+The second argument is the name of a block test from the file.
+
+The block test will be loaded into an in-memory database.
+If loading succeeds, the RPC server is started. Clients will
+be able to interact with the chain defined by the test.
+`,
+}
+
+func runblocktest(ctx *cli.Context) {
+	if len(ctx.Args()) != 2 {
+		utils.Fatalf("This command requires two arguments.")
+	}
+	file, testname := ctx.Args()[0], ctx.Args()[1]
+
+	bt, err := tests.LoadBlockTests(file)
+	if err != nil {
+		utils.Fatalf("%v", err)
+	}
+	test, ok := bt[testname]
+	if !ok {
+		utils.Fatalf("Test file does not contain test named %q", testname)
+	}
+
+	cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
+	cfg.NewDB = func(path string) (ethutil.Database, error) { return ethdb.NewMemDatabase() }
+	ethereum, err := eth.New(cfg)
+	if err != nil {
+		utils.Fatalf("%v", err)
+	}
+
+	// import the genesis block
+	ethereum.ResetWithGenesisBlock(test.Genesis)
+
+	// import pre accounts
+	if err := test.InsertPreState(ethereum.StateDb()); err != nil {
+		utils.Fatalf("could not insert genesis accounts: %v", err)
+	}
+
+	// insert the test blocks, which will execute all transactions
+	chain := ethereum.ChainManager()
+	if err := chain.InsertChain(test.Blocks); err != nil {
+		utils.Fatalf("Block Test load error: %v", err)
+	} else {
+		fmt.Println("Block Test chain loaded, starting ethereum.")
+	}
+	startEth(ctx, ethereum)
+}
diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go
index 4cb2d997903e7727149a2f26dcbe6b9897b9cab7..53746627a02d16d3ea5ad88798530e8b23d8485e 100644
--- a/cmd/ethereum/main.go
+++ b/cmd/ethereum/main.go
@@ -53,6 +53,7 @@ func init() {
 	app.Action = run
 	app.HideVersion = true // we have a command to print the version
 	app.Commands = []cli.Command{
+		blocktestCmd,
 		{
 			Action: version,
 			Name:   "version",
@@ -156,24 +157,26 @@ func main() {
 func run(ctx *cli.Context) {
 	fmt.Printf("Welcome to the FRONTIER\n")
 	utils.HandleInterrupt()
-	eth, err := utils.GetEthereum(ClientIdentifier, Version, ctx)
+	cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
+	ethereum, err := eth.New(cfg)
 	if err != nil {
 		utils.Fatalf("%v", err)
 	}
 
-	startEth(ctx, eth)
+	startEth(ctx, ethereum)
 	// this blocks the thread
-	eth.WaitForShutdown()
+	ethereum.WaitForShutdown()
 }
 
 func runjs(ctx *cli.Context) {
-	eth, err := utils.GetEthereum(ClientIdentifier, Version, ctx)
+	cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
+	ethereum, err := eth.New(cfg)
 	if err != nil {
 		utils.Fatalf("%v", err)
 	}
 
-	startEth(ctx, eth)
-	repl := newJSRE(eth)
+	startEth(ctx, ethereum)
+	repl := newJSRE(ethereum)
 	if len(ctx.Args()) == 0 {
 		repl.interactive()
 	} else {
@@ -181,8 +184,8 @@ func runjs(ctx *cli.Context) {
 			repl.exec(file)
 		}
 	}
-	eth.Stop()
-	eth.WaitForShutdown()
+	ethereum.Stop()
+	ethereum.WaitForShutdown()
 }
 
 func startEth(ctx *cli.Context, eth *eth.Ethereum) {
diff --git a/cmd/mist/main.go b/cmd/mist/main.go
index 9a773e33a89ee9bd461186408d9046403bafb15f..4116783c9d41d8e2b863204e3ab8f113981f58b8 100644
--- a/cmd/mist/main.go
+++ b/cmd/mist/main.go
@@ -28,6 +28,7 @@ import (
 
 	"github.com/codegangsta/cli"
 	"github.com/ethereum/go-ethereum/cmd/utils"
+	"github.com/ethereum/go-ethereum/eth"
 	"github.com/ethereum/go-ethereum/ethutil"
 	"github.com/ethereum/go-ethereum/logger"
 	"github.com/ethereum/go-ethereum/ui/qt/webengine"
@@ -95,7 +96,8 @@ func run(ctx *cli.Context) {
 	tstart := time.Now()
 
 	// TODO: show qml popup instead of exiting if initialization fails.
-	ethereum, err := utils.GetEthereum(ClientIdentifier, Version, ctx)
+	cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
+	ethereum, err := eth.New(cfg)
 	if err != nil {
 		utils.Fatalf("%v", err)
 	}
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 990fb08e0b53118649465ee7492840c8fa3f46b5..6bcd7e8119c75aaaf184448ac7d5a1a6038be45a 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -191,8 +191,8 @@ func GetNodeKey(ctx *cli.Context) (key *ecdsa.PrivateKey) {
 	return key
 }
 
-func GetEthereum(clientID, version string, ctx *cli.Context) (*eth.Ethereum, error) {
-	return eth.New(&eth.Config{
+func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
+	return &eth.Config{
 		Name:           ethutil.MakeName(clientID, version),
 		DataDir:        ctx.GlobalString(DataDirFlag.Name),
 		LogFile:        ctx.GlobalString(LogFileFlag.Name),
@@ -208,7 +208,7 @@ func GetEthereum(clientID, version string, ctx *cli.Context) (*eth.Ethereum, err
 		Shh:            true,
 		Dial:           true,
 		BootNodes:      ctx.GlobalString(BootnodesFlag.Name),
-	})
+	}
 }
 
 func GetChain(ctx *cli.Context) (*core.ChainManager, ethutil.Database, ethutil.Database) {
diff --git a/core/types/block.go b/core/types/block.go
index 50973c804e5973ab7ecb75a4e0a8561c6de845a5..ba6ef601495b9b73fe9044c7b687ab58c4c74257 100644
--- a/core/types/block.go
+++ b/core/types/block.go
@@ -15,7 +15,7 @@ import (
 
 type Header struct {
 	// Hash to the previous block
-	ParentHash ethutil.Bytes
+	ParentHash []byte
 	// Uncles of this block
 	UncleHash []byte
 	// The coin base address
@@ -41,7 +41,7 @@ type Header struct {
 	// Extra data
 	Extra string
 	// Mix digest for quick checking to prevent DOS
-	MixDigest ethutil.Bytes
+	MixDigest []byte
 	// Nonce
 	Nonce []byte
 }
diff --git a/eth/backend.go b/eth/backend.go
index bb203b4a6f1c40141b557e95b63eaf2c5b6e9ac2..346fc43bc0fff6f4b9847a24ff8c33742a975e2e 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -11,6 +11,7 @@ import (
 	"github.com/ethereum/go-ethereum/accounts"
 	"github.com/ethereum/go-ethereum/blockpool"
 	"github.com/ethereum/go-ethereum/core"
+	"github.com/ethereum/go-ethereum/core/types"
 	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/ethdb"
 	"github.com/ethereum/go-ethereum/ethutil"
@@ -61,6 +62,10 @@ type Config struct {
 
 	MinerThreads   int
 	AccountManager *accounts.Manager
+
+	// NewDB is used to create databases.
+	// If nil, the default is to create leveldb databases on disk.
+	NewDB func(path string) (ethutil.Database, error)
 }
 
 func (cfg *Config) parseBootNodes() []*discover.Node {
@@ -120,6 +125,7 @@ type Ethereum struct {
 	blockPool      *blockpool.BlockPool
 	accountManager *accounts.Manager
 	whisper        *whisper.Whisper
+	pow            *ethash.Ethash
 
 	net      *p2p.Server
 	eventMux *event.TypeMux
@@ -138,11 +144,15 @@ func New(config *Config) (*Ethereum, error) {
 	// Boostrap database
 	servlogger := logger.New(config.DataDir, config.LogFile, config.LogLevel, config.LogFormat)
 
-	blockDb, err := ethdb.NewLDBDatabase(path.Join(config.DataDir, "blockchain"))
+	newdb := config.NewDB
+	if newdb == nil {
+		newdb = func(path string) (ethutil.Database, error) { return ethdb.NewLDBDatabase(path) }
+	}
+	blockDb, err := newdb(path.Join(config.DataDir, "blockchain"))
 	if err != nil {
 		return nil, err
 	}
-	stateDb, err := ethdb.NewLDBDatabase(path.Join(config.DataDir, "state"))
+	stateDb, err := newdb(path.Join(config.DataDir, "state"))
 	if err != nil {
 		return nil, err
 	}
@@ -170,16 +180,16 @@ func New(config *Config) (*Ethereum, error) {
 	}
 
 	eth.chainManager = core.NewChainManager(blockDb, stateDb, eth.EventMux())
-	pow := ethash.New(eth.chainManager)
+	eth.pow = ethash.New(eth.chainManager)
 	eth.txPool = core.NewTxPool(eth.EventMux())
-	eth.blockProcessor = core.NewBlockProcessor(stateDb, extraDb, pow, eth.txPool, eth.chainManager, eth.EventMux())
+	eth.blockProcessor = core.NewBlockProcessor(stateDb, extraDb, eth.pow, eth.txPool, eth.chainManager, eth.EventMux())
 	eth.chainManager.SetProcessor(eth.blockProcessor)
 	eth.whisper = whisper.New()
-	eth.miner = miner.New(eth, pow, config.MinerThreads)
+	eth.miner = miner.New(eth, eth.pow, config.MinerThreads)
 
 	hasBlock := eth.chainManager.HasBlock
 	insertChain := eth.chainManager.InsertChain
-	eth.blockPool = blockpool.New(hasBlock, insertChain, pow.Verify)
+	eth.blockPool = blockpool.New(hasBlock, insertChain, eth.pow.Verify)
 
 	netprv, err := config.nodeKey()
 	if err != nil {
@@ -209,6 +219,11 @@ func New(config *Config) (*Ethereum, error) {
 	return eth, nil
 }
 
+func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) {
+	s.chainManager.ResetWithGenesisBlock(gb)
+	s.pow.UpdateCache(true)
+}
+
 func (s *Ethereum) StartMining() error {
 	cb, err := s.accountManager.Coinbase()
 	if err != nil {
diff --git a/tests/blocktest.go b/tests/blocktest.go
new file mode 100644
index 0000000000000000000000000000000000000000..6a9cf5f6dca546366dc94a8a91de4607c731b146
--- /dev/null
+++ b/tests/blocktest.go
@@ -0,0 +1,240 @@
+package tests
+
+import (
+	"bytes"
+	"encoding/hex"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io/ioutil"
+	"math/big"
+	"runtime"
+	"strconv"
+	"strings"
+
+	"github.com/ethereum/go-ethereum/core/types"
+	"github.com/ethereum/go-ethereum/ethutil"
+	"github.com/ethereum/go-ethereum/rlp"
+	"github.com/ethereum/go-ethereum/state"
+)
+
+// Block Test JSON Format
+
+type btJSON struct {
+	Blocks             []btBlock
+	GenesisBlockHeader btHeader
+	Pre                map[string]btAccount
+}
+
+type btAccount struct {
+	Balance string
+	Code    string
+	Nonce   string
+	Storage map[string]string
+}
+
+type btHeader struct {
+	Bloom            string
+	Coinbase         string
+	MixHash          string
+	Nonce            string
+	Number           string
+	ParentHash       string
+	ReceiptTrie      string
+	SeedHash         string
+	StateRoot        string
+	TransactionsTrie string
+	UncleHash        string
+
+	ExtraData  string
+	Difficulty string
+	GasLimit   string
+	GasUsed    string
+	Timestamp  string
+}
+
+type btTransaction struct {
+	Data     string
+	GasLimit string
+	GasPrice string
+	Nonce    string
+	R        string
+	S        string
+	To       string
+	V        string
+	Value    string
+}
+
+type btBlock struct {
+	BlockHeader  *btHeader
+	Rlp          string
+	Transactions []btTransaction
+	UncleHeaders []string
+}
+
+type BlockTest struct {
+	Genesis *types.Block
+	Blocks  []*types.Block
+
+	preAccounts map[string]btAccount
+}
+
+// LoadBlockTests loads a block test JSON file.
+func LoadBlockTests(file string) (map[string]*BlockTest, error) {
+	bt := make(map[string]*btJSON)
+	if err := loadJSON(file, &bt); err != nil {
+		return nil, err
+	}
+	out := make(map[string]*BlockTest)
+	for name, in := range bt {
+		var err error
+		if out[name], err = convertTest(in); err != nil {
+			return nil, fmt.Errorf("bad test %q: %v", err)
+		}
+	}
+	return out, nil
+}
+
+// InsertPreState populates the given database with the genesis
+// accounts defined by the test.
+func (t *BlockTest) InsertPreState(db ethutil.Database) error {
+	statedb := state.New(nil, db)
+	for addrString, acct := range t.preAccounts {
+		// XXX: is is worth it checking for errors here?
+		addr, _ := hex.DecodeString(addrString)
+		code, _ := hex.DecodeString(strings.TrimPrefix(acct.Code, "0x"))
+		balance, _ := new(big.Int).SetString(acct.Balance, 0)
+		nonce, _ := strconv.ParseUint(acct.Nonce, 16, 64)
+
+		obj := statedb.NewStateObject(addr)
+		obj.SetCode(code)
+		obj.SetBalance(balance)
+		obj.SetNonce(nonce)
+		// for k, v := range acct.Storage {
+		// 	obj.SetState(k, v)
+		// }
+	}
+	// sync objects to trie
+	statedb.Update(nil)
+	// sync trie to disk
+	statedb.Sync()
+
+	if !bytes.Equal(t.Genesis.Root(), statedb.Root()) {
+		return errors.New("computed state root does not match genesis block")
+	}
+	return nil
+}
+
+func convertTest(in *btJSON) (out *BlockTest, err error) {
+	// the conversion handles errors by catching panics.
+	// you might consider this ugly, but the alternative (passing errors)
+	// would be much harder to read.
+	defer func() {
+		if recovered := recover(); recovered != nil {
+			buf := make([]byte, 64<<10)
+			buf = buf[:runtime.Stack(buf, false)]
+			err = fmt.Errorf("%v\n%s", recovered, buf)
+		}
+	}()
+	out = &BlockTest{preAccounts: in.Pre}
+	out.Genesis = mustConvertGenesis(in.GenesisBlockHeader)
+	out.Blocks = mustConvertBlocks(in.Blocks)
+	return out, err
+}
+
+func mustConvertGenesis(testGenesis btHeader) *types.Block {
+	hdr := mustConvertHeader(testGenesis)
+	hdr.Number = big.NewInt(0)
+	b := types.NewBlockWithHeader(hdr)
+	b.Td = new(big.Int)
+	b.Reward = new(big.Int)
+	return b
+}
+
+func mustConvertHeader(in btHeader) *types.Header {
+	// hex decode these fields
+	return &types.Header{
+		//SeedHash:    mustConvertBytes(in.SeedHash),
+		MixDigest:   mustConvertBytes(in.MixHash),
+		Bloom:       mustConvertBytes(in.Bloom),
+		ReceiptHash: mustConvertBytes(in.ReceiptTrie),
+		TxHash:      mustConvertBytes(in.TransactionsTrie),
+		Root:        mustConvertBytes(in.StateRoot),
+		Coinbase:    mustConvertBytes(in.Coinbase),
+		UncleHash:   mustConvertBytes(in.UncleHash),
+		ParentHash:  mustConvertBytes(in.ParentHash),
+		Nonce:       mustConvertBytes(in.Nonce),
+		Extra:       string(mustConvertBytes(in.ExtraData)),
+		GasUsed:     mustConvertBigInt10(in.GasUsed),
+		GasLimit:    mustConvertBigInt10(in.GasLimit),
+		Difficulty:  mustConvertBigInt10(in.Difficulty),
+		Time:        mustConvertUint(in.Timestamp),
+	}
+}
+
+func mustConvertBlocks(testBlocks []btBlock) []*types.Block {
+	var out []*types.Block
+	for i, inb := range testBlocks {
+		var b types.Block
+		r := bytes.NewReader(mustConvertBytes(inb.Rlp))
+		if err := rlp.Decode(r, &b); err != nil {
+			panic(fmt.Errorf("invalid block %d: %q", i, inb.Rlp))
+		}
+		out = append(out, &b)
+	}
+	return out
+}
+
+func mustConvertBytes(in string) []byte {
+	out, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
+	if err != nil {
+		panic(fmt.Errorf("invalid hex: %q", in))
+	}
+	return out
+}
+
+func mustConvertBigInt10(in string) *big.Int {
+	out, ok := new(big.Int).SetString(in, 10)
+	if !ok {
+		panic(fmt.Errorf("invalid integer: %q", in))
+	}
+	return out
+}
+
+func mustConvertUint(in string) uint64 {
+	out, err := strconv.ParseUint(in, 0, 64)
+	if err != nil {
+		panic(fmt.Errorf("invalid integer: %q", in))
+	}
+	return out
+}
+
+// loadJSON reads the given file and unmarshals its content.
+func loadJSON(file string, val interface{}) error {
+	content, err := ioutil.ReadFile(file)
+	if err != nil {
+		return err
+	}
+	if err := json.Unmarshal(content, val); err != nil {
+		if syntaxerr, ok := err.(*json.SyntaxError); ok {
+			line := findLine(content, syntaxerr.Offset)
+			return fmt.Errorf("JSON syntax error at %v:%v: %v", file, line, err)
+		}
+		return fmt.Errorf("JSON unmarshal error in %v: %v", file, err)
+	}
+	return nil
+}
+
+// findLine returns the line number for the given offset into data.
+func findLine(data []byte, offset int64) (line int) {
+	line = 1
+	for i, r := range string(data) {
+		if int64(i) >= offset {
+			return
+		}
+		if r == '\n' {
+			line++
+		}
+	}
+	return
+}