diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go
index 18e8481c5c0e77c196d463984e067f7e765775bc..213a4f1a77b4058605983e3e889f202c4bb98ae8 100644
--- a/accounts/abi/bind/backends/simulated.go
+++ b/accounts/abi/bind/backends/simulated.go
@@ -24,10 +24,14 @@ import (
 	"github.com/ethereum/go-ethereum/core"
 	"github.com/ethereum/go-ethereum/core/state"
 	"github.com/ethereum/go-ethereum/core/types"
+	"github.com/ethereum/go-ethereum/core/vm"
 	"github.com/ethereum/go-ethereum/ethdb"
 	"github.com/ethereum/go-ethereum/event"
 )
 
+// Default chain configuration which sets homestead phase at block 0 (i.e. no frontier)
+var chainConfig = &core.ChainConfig{HomesteadBlock: big.NewInt(0)}
+
 // This nil assignment ensures compile time that SimulatedBackend implements bind.ContractBackend.
 var _ bind.ContractBackend = (*SimulatedBackend)(nil)
 
@@ -46,7 +50,7 @@ type SimulatedBackend struct {
 func NewSimulatedBackend(accounts ...core.GenesisAccount) *SimulatedBackend {
 	database, _ := ethdb.NewMemDatabase()
 	core.WriteGenesisBlockForTesting(database, accounts...)
-	blockchain, _ := core.NewBlockChain(database, new(core.FakePow), new(event.TypeMux))
+	blockchain, _ := core.NewBlockChain(database, chainConfig, new(core.FakePow), new(event.TypeMux))
 
 	backend := &SimulatedBackend{
 		database:   database,
@@ -102,7 +106,7 @@ func (b *SimulatedBackend) ContractCall(contract common.Address, data []byte, pe
 		data:     data,
 	}
 	// Execute the call and return
-	vmenv := core.NewEnv(statedb, b.blockchain, msg, block.Header(), nil)
+	vmenv := core.NewEnv(statedb, chainConfig, b.blockchain, msg, block.Header(), vm.Config{})
 	gaspool := new(core.GasPool).AddGas(common.MaxBig)
 
 	out, _, err := core.ApplyMessage(vmenv, msg, gaspool)
@@ -145,7 +149,7 @@ func (b *SimulatedBackend) EstimateGasLimit(sender common.Address, contract *com
 		data:     data,
 	}
 	// Execute the call and return
-	vmenv := core.NewEnv(statedb, b.blockchain, msg, block.Header(), nil)
+	vmenv := core.NewEnv(statedb, chainConfig, b.blockchain, msg, block.Header(), vm.Config{})
 	gaspool := new(core.GasPool).AddGas(common.MaxBig)
 
 	_, gas, err := core.ApplyMessage(vmenv, msg, gaspool)
diff --git a/cmd/ethtest/main.go b/cmd/ethtest/main.go
index e19dca86b466043417b8158f67274b806963582e..3916e297f98c7916b6508cddb31a3962ba5d8e57 100644
--- a/cmd/ethtest/main.go
+++ b/cmd/ethtest/main.go
@@ -27,6 +27,7 @@ import (
 
 	"github.com/codegangsta/cli"
 	"github.com/ethereum/go-ethereum/logger/glog"
+	"github.com/ethereum/go-ethereum/params"
 	"github.com/ethereum/go-ethereum/tests"
 )
 
@@ -73,9 +74,9 @@ func runTestWithReader(test string, r io.Reader) error {
 	var err error
 	switch strings.ToLower(test) {
 	case "bk", "block", "blocktest", "blockchaintest", "blocktests", "blockchaintests":
-		err = tests.RunBlockTestWithReader(r, skipTests)
+		err = tests.RunBlockTestWithReader(params.MainNetHomesteadBlock, r, skipTests)
 	case "st", "state", "statetest", "statetests":
-		err = tests.RunStateTestWithReader(r, skipTests)
+		err = tests.RunStateTestWithReader(tests.RuleSet{params.MainNetHomesteadBlock}, r, skipTests)
 	case "tx", "transactiontest", "transactiontests":
 		err = tests.RunTransactionTestsWithReader(r, skipTests)
 	case "vm", "vmtest", "vmtests":
diff --git a/cmd/evm/main.go b/cmd/evm/main.go
index 2cc70d81becf15dc9d7a572cc89b6602f1cb2758..7d9b3a6c337192651193cc34f338c2b1c7645838 100644
--- a/cmd/evm/main.go
+++ b/cmd/evm/main.go
@@ -33,7 +33,6 @@ import (
 	"github.com/ethereum/go-ethereum/core/vm"
 	"github.com/ethereum/go-ethereum/ethdb"
 	"github.com/ethereum/go-ethereum/logger/glog"
-	"github.com/ethereum/go-ethereum/params"
 )
 
 var (
@@ -106,9 +105,6 @@ func init() {
 }
 
 func run(ctx *cli.Context) {
-	vm.ForceJit = ctx.GlobalBool(ForceJitFlag.Name)
-	vm.EnableJit = !ctx.GlobalBool(DisableJitFlag.Name)
-
 	glog.SetToStderr(true)
 	glog.SetV(ctx.GlobalInt(VerbosityFlag.Name))
 
@@ -118,8 +114,10 @@ func run(ctx *cli.Context) {
 	receiver := statedb.CreateAccount(common.StringToAddress("receiver"))
 	receiver.SetCode(common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name)))
 
-	vmenv := NewEnv(statedb, common.StringToAddress("evmuser"), common.Big(ctx.GlobalString(ValueFlag.Name)), &vm.Config{
-		Debug: ctx.GlobalBool(DebugFlag.Name),
+	vmenv := NewEnv(statedb, common.StringToAddress("evmuser"), common.Big(ctx.GlobalString(ValueFlag.Name)), vm.Config{
+		Debug:     ctx.GlobalBool(DebugFlag.Name),
+		ForceJit:  ctx.GlobalBool(ForceJitFlag.Name),
+		EnableJit: !ctx.GlobalBool(DisableJitFlag.Name),
 	})
 
 	tstart := time.Now()
@@ -180,8 +178,7 @@ type VMEnv struct {
 	evm *vm.EVM
 }
 
-func NewEnv(state *state.StateDB, transactor common.Address, value *big.Int, cfg *vm.Config) *VMEnv {
-	params.HomesteadBlock = new(big.Int)
+func NewEnv(state *state.StateDB, transactor common.Address, value *big.Int, cfg vm.Config) *VMEnv {
 	env := &VMEnv{
 		state:      state,
 		transactor: &transactor,
@@ -194,6 +191,12 @@ func NewEnv(state *state.StateDB, transactor common.Address, value *big.Int, cfg
 	return env
 }
 
+// ruleSet implements vm.RuleSet and will always default to the homestead rule set.
+type ruleSet struct{}
+
+func (ruleSet) IsHomestead(*big.Int) bool { return true }
+
+func (self *VMEnv) RuleSet() vm.RuleSet        { return ruleSet{} }
 func (self *VMEnv) Vm() vm.Vm                  { return self.evm }
 func (self *VMEnv) Db() vm.Database            { return self.state }
 func (self *VMEnv) MakeSnapshot() vm.Database  { return self.state.Copy() }
diff --git a/cmd/geth/js_test.go b/cmd/geth/js_test.go
index af435e68ce2ba78ff8c85d484c4c2a93b8df010b..e0c4dacbce19219bb7c0ea70bc83713be49126e9 100644
--- a/cmd/geth/js_test.go
+++ b/cmd/geth/js_test.go
@@ -106,6 +106,7 @@ func testREPL(t *testing.T, config func(*eth.Config)) (string, *testjethre, *nod
 	core.WriteGenesisBlockForTesting(db, core.GenesisAccount{common.HexToAddress(testAddress), common.String2Big(testBalance)})
 
 	ethConf := &eth.Config{
+		ChainConfig:      &core.ChainConfig{HomesteadBlock: new(big.Int)},
 		TestGenesisState: db,
 		AccountManager:   accman,
 		DocRoot:          "/",
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index a21fe71b540b8a8c78fa6eee9d7dbb7b72fb37c8..5d5ab4559dfaea90060d1f3ad18b3eeaf451d224 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -32,7 +32,9 @@ import (
 	"github.com/ethereum/go-ethereum/accounts"
 	"github.com/ethereum/go-ethereum/cmd/utils"
 	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/core"
 	"github.com/ethereum/go-ethereum/eth"
+	"github.com/ethereum/go-ethereum/ethdb"
 	"github.com/ethereum/go-ethereum/internal/debug"
 	"github.com/ethereum/go-ethereum/logger"
 	"github.com/ethereum/go-ethereum/logger/glog"
@@ -108,7 +110,6 @@ Runs quick benchmark on first GPU found.
 The output of this command is supposed to be machine-readable.
 `,
 		},
-
 		{
 			Name:  "wallet",
 			Usage: "ethereum presale wallet",
@@ -247,6 +248,16 @@ nodes.
 				},
 			},
 		},
+		{
+			Action: initGenesis,
+			Name:   "init",
+			Usage:  "bootstraps and initialises a new genesis block (JSON)",
+			Description: `
+The init command initialises a new genesis block and definition for the network.
+This is a destructive action and changes the network in which you will be
+participating.
+`,
+		},
 		{
 			Action: console,
 			Name:   "console",
@@ -255,7 +266,8 @@ nodes.
 The Geth console is an interactive shell for the JavaScript runtime environment
 which exposes a node admin interface as well as the Ðapp JavaScript API.
 See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console
-`},
+`,
+		},
 		{
 			Action: attach,
 			Name:   "attach",
@@ -347,7 +359,6 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
 		go metrics.CollectProcessMetrics(3 * time.Second)
 
 		utils.SetupNetwork(ctx)
-		utils.SetupVM(ctx)
 		return nil
 	}
 
@@ -417,6 +428,31 @@ func attach(ctx *cli.Context) {
 	}
 }
 
+// initGenesis will initialise the given JSON format genesis file and writes it as
+// the zero'd block (i.e. genesis) or will fail hard if it can't succeed.
+func initGenesis(ctx *cli.Context) {
+	genesisPath := ctx.Args().First()
+	if len(genesisPath) == 0 {
+		utils.Fatalf("must supply path to genesis JSON file")
+	}
+
+	chainDb, err := ethdb.NewLDBDatabase(filepath.Join(utils.MustMakeDataDir(ctx), "chaindata"), 0, 0)
+	if err != nil {
+		utils.Fatalf("could not open database: %v", err)
+	}
+
+	genesisFile, err := os.Open(genesisPath)
+	if err != nil {
+		utils.Fatalf("failed to read genesis file: %v", err)
+	}
+
+	block, err := core.WriteGenesisBlock(chainDb, genesisFile)
+	if err != nil {
+		utils.Fatalf("failed to write genesis block: %v", err)
+	}
+	glog.V(logger.Info).Infof("successfully wrote genesis block and/or chain rule set: %x", block.Hash())
+}
+
 // console starts a new geth node, attaching a JavaScript console to it at the
 // same time.
 func console(ctx *cli.Context) {
diff --git a/cmd/geth/usage.go b/cmd/geth/usage.go
index 55daa63d768a24351e0141994f6cff4d1e982e25..a31532beaa6e5784c5e65aa72f8b8cbc4e245c63 100644
--- a/cmd/geth/usage.go
+++ b/cmd/geth/usage.go
@@ -121,6 +121,7 @@ var AppHelpFlagGroups = []flagGroup{
 		Flags: []cli.Flag{
 			utils.MiningEnabledFlag,
 			utils.MinerThreadsFlag,
+			utils.TargetGasLimitFlag,
 			utils.MiningGPUFlag,
 			utils.AutoDAGFlag,
 			utils.EtherbaseFlag,
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index a00466d0a17ddd9fb948949fb5522f97a5f83f13..3f54b40caf4c05b1abcf984aab3c619a0c582b35 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -34,7 +34,6 @@ import (
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/core"
 	"github.com/ethereum/go-ethereum/core/state"
-	"github.com/ethereum/go-ethereum/core/vm"
 	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/eth"
 	"github.com/ethereum/go-ethereum/ethdb"
@@ -173,6 +172,11 @@ var (
 		Name:  "minergpus",
 		Usage: "List of GPUs to use for mining (e.g. '0,1' will use the first two GPUs found)",
 	}
+	TargetGasLimitFlag = cli.StringFlag{
+		Name:  "targetgaslimit",
+		Usage: "Target gas limit sets the artificial target gas floor for the blocks to mine",
+		Value: params.GenesisGasLimit.String(),
+	}
 	AutoDAGFlag = cli.BoolFlag{
 		Name:  "autodag",
 		Usage: "Enable automatic DAG pregeneration",
@@ -656,6 +660,7 @@ func MakeSystemNode(name, version string, extra []byte, ctx *cli.Context) *node.
 	accman := MakeAccountManager(ctx)
 
 	ethConf := &eth.Config{
+		ChainConfig:             MustMakeChainConfig(ctx),
 		Genesis:                 MakeGenesisBlock(ctx),
 		FastSync:                ctx.GlobalBool(FastSyncFlag.Name),
 		BlockChainVersion:       ctx.GlobalInt(BlockchainVersionFlag.Name),
@@ -701,8 +706,6 @@ func MakeSystemNode(name, version string, extra []byte, ctx *cli.Context) *node.
 			ethConf.Genesis = core.TestNetGenesisBlock()
 		}
 		state.StartingNonce = 1048576 // (2**20)
-		// overwrite homestead block
-		params.HomesteadBlock = params.TestNetHomesteadBlock
 
 	case ctx.GlobalBool(DevModeFlag.Name):
 		// Override the base network stack configs
@@ -758,25 +761,56 @@ func SetupNetwork(ctx *cli.Context) {
 		core.BlockReward = big.NewInt(1.5e+18)
 		core.ExpDiffPeriod = big.NewInt(math.MaxInt64)
 	}
+	params.TargetGasLimit = common.String2Big(ctx.GlobalString(TargetGasLimitFlag.Name))
 }
 
-// SetupVM configured the VM package's global settings
-func SetupVM(ctx *cli.Context) {
-	vm.EnableJit = ctx.GlobalBool(VMEnableJitFlag.Name)
-	vm.ForceJit = ctx.GlobalBool(VMForceJitFlag.Name)
-	vm.SetJITCacheSize(ctx.GlobalInt(VMJitCacheFlag.Name))
+// MustMakeChainConfig reads the chain configuration from the given database.
+func MustMakeChainConfig(ctx *cli.Context) *core.ChainConfig {
+	var (
+		db      = MakeChainDatabase(ctx)
+		genesis = core.GetBlock(db, core.GetCanonicalHash(db, 0))
+	)
+	defer db.Close()
+
+	chainConfig, err := core.GetChainConfig(db, genesis.Hash())
+	if err != nil {
+		if err != core.ChainConfigNotFoundErr {
+			Fatalf("Could not make chain configuration: %v", err)
+		}
+		var homesteadBlockNo *big.Int
+		if ctx.GlobalBool(TestNetFlag.Name) {
+			homesteadBlockNo = params.TestNetHomesteadBlock
+		} else {
+			homesteadBlockNo = params.MainNetHomesteadBlock
+		}
+
+		chainConfig = &core.ChainConfig{
+			HomesteadBlock: homesteadBlockNo,
+		}
+	}
+	return chainConfig
 }
 
-// MakeChain creates a chain manager from set command line flags.
-func MakeChain(ctx *cli.Context) (chain *core.BlockChain, chainDb ethdb.Database) {
-	datadir := MustMakeDataDir(ctx)
-	cache := ctx.GlobalInt(CacheFlag.Name)
-	handles := MakeDatabaseHandles()
+// MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
+func MakeChainDatabase(ctx *cli.Context) ethdb.Database {
+	var (
+		datadir = MustMakeDataDir(ctx)
+		cache   = ctx.GlobalInt(CacheFlag.Name)
+		handles = MakeDatabaseHandles()
+	)
 
-	var err error
-	if chainDb, err = ethdb.NewLDBDatabase(filepath.Join(datadir, "chaindata"), cache, handles); err != nil {
+	chainDb, err := ethdb.NewLDBDatabase(filepath.Join(datadir, "chaindata"), cache, handles)
+	if err != nil {
 		Fatalf("Could not open database: %v", err)
 	}
+	return chainDb
+}
+
+// MakeChain creates a chain manager from set command line flags.
+func MakeChain(ctx *cli.Context) (chain *core.BlockChain, chainDb ethdb.Database) {
+	var err error
+	chainDb = MakeChainDatabase(ctx)
+
 	if ctx.GlobalBool(OlympicFlag.Name) {
 		_, err := core.WriteTestNetGenesisBlock(chainDb)
 		if err != nil {
@@ -784,10 +818,10 @@ func MakeChain(ctx *cli.Context) (chain *core.BlockChain, chainDb ethdb.Database
 		}
 	}
 
-	eventMux := new(event.TypeMux)
-	pow := ethash.New()
-	//genesis := core.GenesisBlock(uint64(ctx.GlobalInt(GenesisNonceFlag.Name)), blockDB)
-	chain, err = core.NewBlockChain(chainDb, pow, eventMux)
+	chainConfig := MustMakeChainConfig(ctx)
+
+	var eventMux event.TypeMux
+	chain, err = core.NewBlockChain(chainDb, chainConfig, ethash.New(), &eventMux)
 	if err != nil {
 		Fatalf("Could not start chainmanager: %v", err)
 	}
diff --git a/common/debug.go b/common/debug.go
index fa93d7bda55846fd239d51e50fe546a05ef7fc52..61acd8ce70f8b77e4b4ffb581e996d69fef48e03 100644
--- a/common/debug.go
+++ b/common/debug.go
@@ -21,8 +21,10 @@ import (
 	"os"
 	"runtime"
 	"runtime/debug"
+	"strings"
 )
 
+// Report gives off a warning requesting the user to submit an issue to the github tracker.
 func Report(extra ...interface{}) {
 	fmt.Fprintln(os.Stderr, "You've encountered a sought after, hard to reproduce bug. Please report this to the developers <3 https://github.com/ethereum/go-ethereum/issues")
 	fmt.Fprintln(os.Stderr, extra...)
@@ -34,3 +36,17 @@ func Report(extra ...interface{}) {
 
 	fmt.Fprintln(os.Stderr, "#### BUG! PLEASE REPORT ####")
 }
+
+// PrintDepricationWarning prinst the given string in a box using fmt.Println.
+func PrintDepricationWarning(str string) {
+	line := strings.Repeat("#", len(str)+4)
+	emptyLine := strings.Repeat(" ", len(str))
+	fmt.Printf(`
+%s
+# %s #
+# %s #
+# %s #
+%s
+
+`, line, emptyLine, str, emptyLine, line)
+}
diff --git a/common/registrar/ethreg/api.go b/common/registrar/ethreg/api.go
index 60a97f4ce30b7fe5d7ead80ae4c05491f929e4be..d035616f2ccab19ea770cdd9912fb34104405e6d 100644
--- a/common/registrar/ethreg/api.go
+++ b/common/registrar/ethreg/api.go
@@ -27,6 +27,7 @@ import (
 	"github.com/ethereum/go-ethereum/core"
 	"github.com/ethereum/go-ethereum/core/state"
 	"github.com/ethereum/go-ethereum/core/types"
+	"github.com/ethereum/go-ethereum/core/vm"
 	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/ethdb"
 	"github.com/ethereum/go-ethereum/logger"
@@ -35,6 +36,7 @@ import (
 
 // registryAPIBackend is a backend for an Ethereum Registry.
 type registryAPIBackend struct {
+	config  *core.ChainConfig
 	bc      *core.BlockChain
 	chainDb ethdb.Database
 	txPool  *core.TxPool
@@ -43,12 +45,22 @@ type registryAPIBackend struct {
 
 // PrivateRegistarAPI offers various functions to access the Ethereum registry.
 type PrivateRegistarAPI struct {
-	be *registryAPIBackend
+	config *core.ChainConfig
+	be     *registryAPIBackend
 }
 
 // NewPrivateRegistarAPI creates a new PrivateRegistarAPI instance.
-func NewPrivateRegistarAPI(bc *core.BlockChain, chainDb ethdb.Database, txPool *core.TxPool, am *accounts.Manager) *PrivateRegistarAPI {
-	return &PrivateRegistarAPI{&registryAPIBackend{bc, chainDb, txPool, am}}
+func NewPrivateRegistarAPI(config *core.ChainConfig, bc *core.BlockChain, chainDb ethdb.Database, txPool *core.TxPool, am *accounts.Manager) *PrivateRegistarAPI {
+	return &PrivateRegistarAPI{
+		config: config,
+		be: &registryAPIBackend{
+			config:  config,
+			bc:      bc,
+			chainDb: chainDb,
+			txPool:  txPool,
+			am:      am,
+		},
+	}
 }
 
 // SetGlobalRegistrar allows clients to set the global registry for the node.
@@ -179,7 +191,7 @@ func (be *registryAPIBackend) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr
 	}
 
 	header := be.bc.CurrentBlock().Header()
-	vmenv := core.NewEnv(statedb, be.bc, msg, header, nil)
+	vmenv := core.NewEnv(statedb, be.config, be.bc, msg, header, vm.Config{})
 	gp := new(core.GasPool).AddGas(common.MaxBig)
 	res, gas, err := core.ApplyMessage(vmenv, msg, gp)
 
diff --git a/core/bench_test.go b/core/bench_test.go
index 0ff847ed51eeda9c60a1e0cf4baad845f74f23cd..ac5b57bc8a37e0d7c6af614303d1a61ff46bc48b 100644
--- a/core/bench_test.go
+++ b/core/bench_test.go
@@ -168,7 +168,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
 	// Time the insertion of the new chain.
 	// State and blocks are stored in the same DB.
 	evmux := new(event.TypeMux)
-	chainman, _ := NewBlockChain(db, FakePow{}, evmux)
+	chainman, _ := NewBlockChain(db, &ChainConfig{HomesteadBlock: new(big.Int)}, FakePow{}, evmux)
 	defer chainman.Stop()
 	b.ReportAllocs()
 	b.ResetTimer()
diff --git a/core/block_validator.go b/core/block_validator.go
index 4d710ae3f59e9babac89a9ac64dd9414c423b599..747e61ccc8e97de55575bb6ea8521d76b25dd238 100644
--- a/core/block_validator.go
+++ b/core/block_validator.go
@@ -41,15 +41,17 @@ var (
 //
 // BlockValidator implements Validator.
 type BlockValidator struct {
-	bc  *BlockChain // Canonical block chain
-	Pow pow.PoW     // Proof of work used for validating
+	config *ChainConfig // Chain configuration options
+	bc     *BlockChain  // Canonical block chain
+	Pow    pow.PoW      // Proof of work used for validating
 }
 
 // NewBlockValidator returns a new block validator which is safe for re-use
-func NewBlockValidator(blockchain *BlockChain, pow pow.PoW) *BlockValidator {
+func NewBlockValidator(config *ChainConfig, blockchain *BlockChain, pow pow.PoW) *BlockValidator {
 	validator := &BlockValidator{
-		Pow: pow,
-		bc:  blockchain,
+		config: config,
+		Pow:    pow,
+		bc:     blockchain,
 	}
 	return validator
 }
@@ -80,7 +82,7 @@ func (v *BlockValidator) ValidateBlock(block *types.Block) error {
 
 	header := block.Header()
 	// validate the block header
-	if err := ValidateHeader(v.Pow, header, parent.Header(), false, false); err != nil {
+	if err := ValidateHeader(v.config, v.Pow, header, parent.Header(), false, false); err != nil {
 		return err
 	}
 	// verify the uncles are correctly rewarded
@@ -175,7 +177,7 @@ func (v *BlockValidator) VerifyUncles(block, parent *types.Block) error {
 			return UncleError("uncle[%d](%x)'s parent is not ancestor (%x)", i, hash[:4], uncle.ParentHash[0:4])
 		}
 
-		if err := ValidateHeader(v.Pow, uncle, ancestors[uncle.ParentHash].Header(), true, true); err != nil {
+		if err := ValidateHeader(v.config, v.Pow, uncle, ancestors[uncle.ParentHash].Header(), true, true); err != nil {
 			return ValidationError(fmt.Sprintf("uncle[%d](%x) header invalid: %v", i, hash[:4], err))
 		}
 	}
@@ -195,13 +197,13 @@ func (v *BlockValidator) ValidateHeader(header, parent *types.Header, checkPow b
 	if v.bc.HasHeader(header.Hash()) {
 		return nil
 	}
-	return ValidateHeader(v.Pow, header, parent, checkPow, false)
+	return ValidateHeader(v.config, v.Pow, header, parent, checkPow, false)
 }
 
 // Validates a header. Returns an error if the header is invalid.
 //
 // See YP section 4.3.4. "Block Header Validity"
-func ValidateHeader(pow pow.PoW, header *types.Header, parent *types.Header, checkPow, uncle bool) error {
+func ValidateHeader(config *ChainConfig, pow pow.PoW, header *types.Header, parent *types.Header, checkPow, uncle bool) error {
 	if big.NewInt(int64(len(header.Extra))).Cmp(params.MaximumExtraDataSize) == 1 {
 		return fmt.Errorf("Header extra data too long (%d)", len(header.Extra))
 	}
@@ -219,7 +221,7 @@ func ValidateHeader(pow pow.PoW, header *types.Header, parent *types.Header, che
 		return BlockEqualTSErr
 	}
 
-	expd := CalcDifficulty(header.Time.Uint64(), parent.Time.Uint64(), parent.Number, parent.Difficulty)
+	expd := CalcDifficulty(config, header.Time.Uint64(), parent.Time.Uint64(), parent.Number, parent.Difficulty)
 	if expd.Cmp(header.Difficulty) != 0 {
 		return fmt.Errorf("Difficulty check failed for header %v, %v", header.Difficulty, expd)
 	}
@@ -251,8 +253,8 @@ func ValidateHeader(pow pow.PoW, header *types.Header, parent *types.Header, che
 // CalcDifficulty is the difficulty adjustment algorithm. It returns
 // the difficulty that a new block should have when created at time
 // given the parent block's time and difficulty.
-func CalcDifficulty(time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
-	if params.IsHomestead(new(big.Int).Add(parentNumber, common.Big1)) {
+func CalcDifficulty(config *ChainConfig, time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
+	if config.IsHomestead(new(big.Int).Add(parentNumber, common.Big1)) {
 		return calcDifficultyHomestead(time, parentTime, parentNumber, parentDiff)
 	} else {
 		return calcDifficultyFrontier(time, parentTime, parentNumber, parentDiff)
@@ -363,11 +365,11 @@ func CalcGasLimit(parent *types.Block) *big.Int {
 	gl = gl.Add(gl, contrib)
 	gl.Set(common.BigMax(gl, params.MinGasLimit))
 
-	// however, if we're now below the target (GenesisGasLimit) we increase the
+	// however, if we're now below the target (TargetGasLimit) we increase the
 	// limit as much as we can (parentGasLimit / 1024 -1)
-	if gl.Cmp(params.GenesisGasLimit) < 0 {
+	if gl.Cmp(params.TargetGasLimit) < 0 {
 		gl.Add(parent.GasLimit(), decay)
-		gl.Set(common.BigMin(gl, params.GenesisGasLimit))
+		gl.Set(common.BigMin(gl, params.TargetGasLimit))
 	}
 	return gl
 }
diff --git a/core/block_validator_test.go b/core/block_validator_test.go
index 2c4a97b457865d151ce2098ba60000c8bd646b91..c6daf9e7f3515e17a84fe6008089e98e0e29499e 100644
--- a/core/block_validator_test.go
+++ b/core/block_validator_test.go
@@ -30,12 +30,16 @@ import (
 	"github.com/ethereum/go-ethereum/pow/ezp"
 )
 
+func testChainConfig() *ChainConfig {
+	return &ChainConfig{HomesteadBlock: big.NewInt(0)}
+}
+
 func proc() (Validator, *BlockChain) {
 	db, _ := ethdb.NewMemDatabase()
 	var mux event.TypeMux
 
 	WriteTestNetGenesisBlock(db)
-	blockchain, err := NewBlockChain(db, thePow(), &mux)
+	blockchain, err := NewBlockChain(db, testChainConfig(), thePow(), &mux)
 	if err != nil {
 		fmt.Println(err)
 	}
@@ -49,13 +53,14 @@ func TestNumber(t *testing.T) {
 	statedb, _ := state.New(chain.Genesis().Root(), chain.chainDb)
 	header := makeHeader(chain.Genesis(), statedb)
 	header.Number = big.NewInt(3)
-	err := ValidateHeader(pow, header, chain.Genesis().Header(), false, false)
+	cfg := testChainConfig()
+	err := ValidateHeader(cfg, pow, header, chain.Genesis().Header(), false, false)
 	if err != BlockNumberErr {
 		t.Errorf("expected block number error, got %q", err)
 	}
 
 	header = makeHeader(chain.Genesis(), statedb)
-	err = ValidateHeader(pow, header, chain.Genesis().Header(), false, false)
+	err = ValidateHeader(cfg, pow, header, chain.Genesis().Header(), false, false)
 	if err == BlockNumberErr {
 		t.Errorf("didn't expect block number error")
 	}
diff --git a/core/blockchain.go b/core/blockchain.go
index 2c3c2bb5c2f91d86d2b1326271171d2a1677601f..177a3bbcea104ca9f985a80df0330418133001f5 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -80,11 +80,12 @@ const (
 // included in the canonical one where as GetBlockByNumber always represents the
 // canonical chain.
 type BlockChain struct {
+	config *ChainConfig // chain & network configuration
+
 	hc           *HeaderChain
 	chainDb      ethdb.Database
 	eventMux     *event.TypeMux
 	genesisBlock *types.Block
-	vmConfig     *vm.Config
 
 	mu      sync.RWMutex // global mutex for locking chain operations
 	chainmu sync.RWMutex // blockchain insertion lock
@@ -113,13 +114,14 @@ type BlockChain struct {
 // NewBlockChain returns a fully initialised block chain using information
 // available in the database. It initialiser the default Ethereum Validator and
 // Processor.
-func NewBlockChain(chainDb ethdb.Database, pow pow.PoW, mux *event.TypeMux) (*BlockChain, error) {
+func NewBlockChain(chainDb ethdb.Database, config *ChainConfig, pow pow.PoW, mux *event.TypeMux) (*BlockChain, error) {
 	bodyCache, _ := lru.New(bodyCacheLimit)
 	bodyRLPCache, _ := lru.New(bodyCacheLimit)
 	blockCache, _ := lru.New(blockCacheLimit)
 	futureBlocks, _ := lru.New(maxFutureBlocks)
 
 	bc := &BlockChain{
+		config:       config,
 		chainDb:      chainDb,
 		eventMux:     mux,
 		quit:         make(chan struct{}),
@@ -129,24 +131,21 @@ func NewBlockChain(chainDb ethdb.Database, pow pow.PoW, mux *event.TypeMux) (*Bl
 		futureBlocks: futureBlocks,
 		pow:          pow,
 	}
-	bc.SetValidator(NewBlockValidator(bc, pow))
-	bc.SetProcessor(NewStateProcessor(bc))
+	bc.SetValidator(NewBlockValidator(config, bc, pow))
+	bc.SetProcessor(NewStateProcessor(config, bc))
 
 	gv := func() HeaderValidator { return bc.Validator() }
 	var err error
-	bc.hc, err = NewHeaderChain(chainDb, gv, bc.getProcInterrupt)
+	bc.hc, err = NewHeaderChain(chainDb, config, gv, bc.getProcInterrupt)
 	if err != nil {
 		return nil, err
 	}
 
 	bc.genesisBlock = bc.GetBlockByNumber(0)
 	if bc.genesisBlock == nil {
-		bc.genesisBlock, err = WriteDefaultGenesisBlock(chainDb)
-		if err != nil {
-			return nil, err
-		}
-		glog.V(logger.Info).Infoln("WARNING: Wrote default ethereum genesis block")
+		return nil, ErrNoGenesis
 	}
+
 	if err := bc.loadLastState(); err != nil {
 		return nil, err
 	}
@@ -163,10 +162,6 @@ func NewBlockChain(chainDb ethdb.Database, pow pow.PoW, mux *event.TypeMux) (*Bl
 	return bc, nil
 }
 
-func (self *BlockChain) SetConfig(vmConfig *vm.Config) {
-	self.vmConfig = vmConfig
-}
-
 func (self *BlockChain) getProcInterrupt() bool {
 	return atomic.LoadInt32(&self.procInterrupt) == 1
 }
@@ -896,7 +891,7 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
 			return i, err
 		}
 		// Process block using the parent state as reference point.
-		receipts, logs, usedGas, err := self.processor.Process(block, statedb, self.vmConfig)
+		receipts, logs, usedGas, err := self.processor.Process(block, statedb, self.config.VmConfig)
 		if err != nil {
 			reportBlock(block, err)
 			return i, err
diff --git a/core/blockchain_test.go b/core/blockchain_test.go
index d7cd24fa832344ad57e04da447e121c9a0b89010..876dd2ba15e2c2093e2c24b7fd3d3da731cdf82a 100644
--- a/core/blockchain_test.go
+++ b/core/blockchain_test.go
@@ -53,7 +53,7 @@ func thePow() pow.PoW {
 func theBlockChain(db ethdb.Database, t *testing.T) *BlockChain {
 	var eventMux event.TypeMux
 	WriteTestNetGenesisBlock(db)
-	blockchain, err := NewBlockChain(db, thePow(), &eventMux)
+	blockchain, err := NewBlockChain(db, testChainConfig(), thePow(), &eventMux)
 	if err != nil {
 		t.Error("failed creating blockchain:", err)
 		t.FailNow()
@@ -141,7 +141,7 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
 		if err != nil {
 			return err
 		}
-		receipts, _, usedGas, err := blockchain.Processor().Process(block, statedb, nil)
+		receipts, _, usedGas, err := blockchain.Processor().Process(block, statedb, vm.Config{})
 		if err != nil {
 			reportBlock(block, err)
 			return err
@@ -435,7 +435,7 @@ func (bproc) ValidateHeader(*types.Header, *types.Header, bool) error { return n
 func (bproc) ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas *big.Int) error {
 	return nil
 }
-func (bproc) Process(block *types.Block, statedb *state.StateDB, cfg *vm.Config) (types.Receipts, vm.Logs, *big.Int, error) {
+func (bproc) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, vm.Logs, *big.Int, error) {
 	return nil, nil, nil, nil
 }
 
@@ -473,13 +473,14 @@ func makeBlockChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.B
 func chm(genesis *types.Block, db ethdb.Database) *BlockChain {
 	var eventMux event.TypeMux
 	bc := &BlockChain{
-		chainDb: db,
+		chainDb:      db,
 		genesisBlock: genesis,
-		eventMux: &eventMux,
-		pow: FakePow{},
+		eventMux:     &eventMux,
+		pow:          FakePow{},
+		config:       testChainConfig(),
 	}
 	valFn := func() HeaderValidator { return bc.Validator() }
-	bc.hc, _ = NewHeaderChain(db, valFn, bc.getProcInterrupt)
+	bc.hc, _ = NewHeaderChain(db, testChainConfig(), valFn, bc.getProcInterrupt)
 	bc.bodyCache, _ = lru.New(100)
 	bc.bodyRLPCache, _ = lru.New(100)
 	bc.blockCache, _ = lru.New(100)
@@ -613,7 +614,7 @@ func testReorgBadHashes(t *testing.T, full bool) {
 		defer func() { delete(BadHashes, headers[3].Hash()) }()
 	}
 	// Create a new chain manager and check it rolled back the state
-	ncm, err := NewBlockChain(db, FakePow{}, new(event.TypeMux))
+	ncm, err := NewBlockChain(db, testChainConfig(), FakePow{}, new(event.TypeMux))
 	if err != nil {
 		t.Fatalf("failed to create new chain manager: %v", err)
 	}
@@ -667,7 +668,7 @@ func testInsertNonceError(t *testing.T, full bool) {
 			failHash = headers[failAt].Hash()
 
 			blockchain.pow = failPow{failNum}
-			blockchain.validator = NewBlockValidator(blockchain, failPow{failNum})
+			blockchain.validator = NewBlockValidator(testChainConfig(), blockchain, failPow{failNum})
 
 			failRes, err = blockchain.InsertHeaderChain(headers, 1)
 		}
@@ -733,7 +734,7 @@ func TestFastVsFullChains(t *testing.T) {
 	archiveDb, _ := ethdb.NewMemDatabase()
 	WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds})
 
-	archive, _ := NewBlockChain(archiveDb, FakePow{}, new(event.TypeMux))
+	archive, _ := NewBlockChain(archiveDb, testChainConfig(), FakePow{}, new(event.TypeMux))
 
 	if n, err := archive.InsertChain(blocks); err != nil {
 		t.Fatalf("failed to process block %d: %v", n, err)
@@ -741,7 +742,7 @@ func TestFastVsFullChains(t *testing.T) {
 	// Fast import the chain as a non-archive node to test
 	fastDb, _ := ethdb.NewMemDatabase()
 	WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds})
-	fast, _ := NewBlockChain(fastDb, FakePow{}, new(event.TypeMux))
+	fast, _ := NewBlockChain(fastDb, testChainConfig(), FakePow{}, new(event.TypeMux))
 
 	headers := make([]*types.Header, len(blocks))
 	for i, block := range blocks {
@@ -817,7 +818,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
 	archiveDb, _ := ethdb.NewMemDatabase()
 	WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds})
 
-	archive, _ := NewBlockChain(archiveDb, FakePow{}, new(event.TypeMux))
+	archive, _ := NewBlockChain(archiveDb, testChainConfig(), FakePow{}, new(event.TypeMux))
 
 	if n, err := archive.InsertChain(blocks); err != nil {
 		t.Fatalf("failed to process block %d: %v", n, err)
@@ -829,7 +830,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
 	// Import the chain as a non-archive node and ensure all pointers are updated
 	fastDb, _ := ethdb.NewMemDatabase()
 	WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds})
-	fast, _ := NewBlockChain(fastDb, FakePow{}, new(event.TypeMux))
+	fast, _ := NewBlockChain(fastDb, testChainConfig(), FakePow{}, new(event.TypeMux))
 
 	headers := make([]*types.Header, len(blocks))
 	for i, block := range blocks {
@@ -848,7 +849,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
 	// Import the chain as a light node and ensure all pointers are updated
 	lightDb, _ := ethdb.NewMemDatabase()
 	WriteGenesisBlockForTesting(lightDb, GenesisAccount{address, funds})
-	light, _ := NewBlockChain(lightDb, FakePow{}, new(event.TypeMux))
+	light, _ := NewBlockChain(lightDb, testChainConfig(), FakePow{}, new(event.TypeMux))
 
 	if n, err := light.InsertHeaderChain(headers, 1); err != nil {
 		t.Fatalf("failed to insert header %d: %v", n, err)
@@ -913,7 +914,7 @@ func TestChainTxReorgs(t *testing.T) {
 	})
 	// Import the chain. This runs all block validation rules.
 	evmux := &event.TypeMux{}
-	blockchain, _ := NewBlockChain(db, FakePow{}, evmux)
+	blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux)
 	if i, err := blockchain.InsertChain(chain); err != nil {
 		t.Fatalf("failed to insert original chain[%d]: %v", i, err)
 	}
@@ -986,7 +987,7 @@ func TestLogReorgs(t *testing.T) {
 	)
 
 	evmux := &event.TypeMux{}
-	blockchain, _ := NewBlockChain(db, FakePow{}, evmux)
+	blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux)
 
 	subs := evmux.Subscribe(RemovedLogsEvent{})
 	chain, _ := GenerateChain(genesis, db, 2, func(i int, gen *BlockGen) {
@@ -1022,25 +1023,23 @@ func TestReorgSideEvent(t *testing.T) {
 	)
 
 	evmux := &event.TypeMux{}
-	blockchain, _ := NewBlockChain(db, FakePow{}, evmux)
+	blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux)
 
-	chain, _ := GenerateChain(genesis, db, 3, func(i int, gen *BlockGen) {
-		if i == 2 {
-			gen.OffsetTime(9)
-		}
-	})
+	chain, _ := GenerateChain(genesis, db, 3, func(i int, gen *BlockGen) {})
 	if _, err := blockchain.InsertChain(chain); err != nil {
 		t.Fatalf("failed to insert chain: %v", err)
 	}
 
 	replacementBlocks, _ := GenerateChain(genesis, db, 4, func(i int, gen *BlockGen) {
 		tx, err := types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), nil).SignECDSA(key1)
+		if i == 2 {
+			gen.OffsetTime(-1)
+		}
 		if err != nil {
 			t.Fatalf("failed to create tx: %v", err)
 		}
 		gen.AddTx(tx)
 	})
-
 	subs := evmux.Subscribe(ChainSideEvent{})
 	if _, err := blockchain.InsertChain(replacementBlocks); err != nil {
 		t.Fatalf("failed to insert chain: %v", err)
diff --git a/core/chain_makers.go b/core/chain_makers.go
index 7ae3c98b06c89276a734377632612c455db01870..ef0ac66d1b47c17b03fc4f7992476bc07baa7d13 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -23,11 +23,21 @@ import (
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/core/state"
 	"github.com/ethereum/go-ethereum/core/types"
+	"github.com/ethereum/go-ethereum/core/vm"
 	"github.com/ethereum/go-ethereum/ethdb"
 	"github.com/ethereum/go-ethereum/event"
 	"github.com/ethereum/go-ethereum/pow"
 )
 
+/*
+ * TODO: move this to another package.
+ */
+
+// MakeChainConfig returns a new ChainConfig with the ethereum default chain settings.
+func MakeChainConfig() *ChainConfig {
+	return &ChainConfig{HomesteadBlock: big.NewInt(0)}
+}
+
 // FakePow is a non-validating proof of work implementation.
 // It returns true from Verify for any block.
 type FakePow struct{}
@@ -91,7 +101,7 @@ func (b *BlockGen) AddTx(tx *types.Transaction) {
 		b.SetCoinbase(common.Address{})
 	}
 	b.statedb.StartRecord(tx.Hash(), common.Hash{}, len(b.txs))
-	receipt, _, _, err := ApplyTransaction(nil, b.gasPool, b.statedb, b.header, tx, b.header.GasUsed, nil)
+	receipt, _, _, err := ApplyTransaction(MakeChainConfig(), nil, b.gasPool, b.statedb, b.header, tx, b.header.GasUsed, vm.Config{})
 	if err != nil {
 		panic(err)
 	}
@@ -148,7 +158,7 @@ func (b *BlockGen) OffsetTime(seconds int64) {
 	if b.header.Time.Cmp(b.parent.Header().Time) <= 0 {
 		panic("block time out of range")
 	}
-	b.header.Difficulty = CalcDifficulty(b.header.Time.Uint64(), b.parent.Time().Uint64(), b.parent.Number(), b.parent.Difficulty())
+	b.header.Difficulty = CalcDifficulty(MakeChainConfig(), b.header.Time.Uint64(), b.parent.Time().Uint64(), b.parent.Number(), b.parent.Difficulty())
 }
 
 // GenerateChain creates a chain of n blocks. The first block's
@@ -203,7 +213,7 @@ func makeHeader(parent *types.Block, state *state.StateDB) *types.Header {
 		Root:       state.IntermediateRoot(),
 		ParentHash: parent.Hash(),
 		Coinbase:   parent.Coinbase(),
-		Difficulty: CalcDifficulty(time.Uint64(), new(big.Int).Sub(time, big.NewInt(10)).Uint64(), parent.Number(), parent.Difficulty()),
+		Difficulty: CalcDifficulty(MakeChainConfig(), time.Uint64(), new(big.Int).Sub(time, big.NewInt(10)).Uint64(), parent.Number(), parent.Difficulty()),
 		GasLimit:   CalcGasLimit(parent),
 		GasUsed:    new(big.Int),
 		Number:     new(big.Int).Add(parent.Number(), common.Big1),
@@ -222,7 +232,7 @@ func newCanonical(n int, full bool) (ethdb.Database, *BlockChain, error) {
 	// Initialize a fresh chain with only a genesis block
 	genesis, _ := WriteTestNetGenesisBlock(db)
 
-	blockchain, _ := NewBlockChain(db, FakePow{}, evmux)
+	blockchain, _ := NewBlockChain(db, MakeChainConfig(), FakePow{}, evmux)
 	// Create and inject the requested chain
 	if n == 0 {
 		return db, blockchain, nil
diff --git a/core/chain_makers_test.go b/core/chain_makers_test.go
index b9c1d89b77c63d7e722a4058b7d1224267aa7e1d..32c3efe8da0ef4b3144895f33c30dedc5abe5b2a 100644
--- a/core/chain_makers_test.go
+++ b/core/chain_makers_test.go
@@ -77,7 +77,7 @@ func ExampleGenerateChain() {
 
 	// Import the chain. This runs all block validation rules.
 	evmux := &event.TypeMux{}
-	blockchain, _ := NewBlockChain(db, FakePow{}, evmux)
+	blockchain, _ := NewBlockChain(db, MakeChainConfig(), FakePow{}, evmux)
 	if i, err := blockchain.InsertChain(chain); err != nil {
 		fmt.Printf("insert error (block %d): %v\n", i, err)
 		return
diff --git a/core/config.go b/core/config.go
new file mode 100644
index 0000000000000000000000000000000000000000..81ca76aa312cea58664610760611a65413dd53eb
--- /dev/null
+++ b/core/config.go
@@ -0,0 +1,46 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package core
+
+import (
+	"errors"
+	"math/big"
+
+	"github.com/ethereum/go-ethereum/core/vm"
+)
+
+var ChainConfigNotFoundErr = errors.New("ChainConfig not found") // general config not found error
+
+// ChainConfig is the core config which determines the blockchain settings.
+//
+// ChainConfig is stored in the database on a per block basis. This means
+// that any network, identified by its genesis block, can have its own
+// set of configuration options.
+type ChainConfig struct {
+	HomesteadBlock *big.Int // homestead switch block
+
+	VmConfig vm.Config `json:"-"`
+}
+
+// IsHomestead returns whether num is either equal to the homestead block or greater.
+func (c *ChainConfig) IsHomestead(num *big.Int) bool {
+	if num == nil {
+		return false
+	}
+
+	return num.Cmp(c.HomesteadBlock) >= 0
+}
diff --git a/core/database_util.go b/core/database_util.go
index fd2b4c312458b5d0e9da089e9cc765741b0ab0c2..e1e8136d1f74f3ca5e44872867428806db028bc5 100644
--- a/core/database_util.go
+++ b/core/database_util.go
@@ -19,6 +19,7 @@ package core
 import (
 	"bytes"
 	"encoding/binary"
+	"encoding/json"
 	"fmt"
 	"math/big"
 
@@ -50,6 +51,8 @@ var (
 	MIPMapLevels = []uint64{1000000, 500000, 100000, 50000, 1000}
 
 	blockHashPrefix = []byte("block-hash-") // [deprecated by the header/block split, remove eventually]
+
+	configPrefix = []byte("ethereum-config-") // config prefix for the db
 )
 
 // GetCanonicalHash retrieves a hash assigned to a canonical block number.
@@ -527,3 +530,34 @@ func WriteBlockChainVersion(db ethdb.Database, vsn int) {
 	enc, _ := rlp.EncodeToBytes(uint(vsn))
 	db.Put([]byte("BlockchainVersion"), enc)
 }
+
+// WriteChainConfig writes the chain config settings to the database.
+func WriteChainConfig(db ethdb.Database, hash common.Hash, cfg *ChainConfig) error {
+	// short circuit and ignore if nil config. GetChainConfig
+	// will return a default.
+	if cfg == nil {
+		return nil
+	}
+
+	jsonChainConfig, err := json.Marshal(cfg)
+	if err != nil {
+		return err
+	}
+
+	return db.Put(append(configPrefix, hash[:]...), jsonChainConfig)
+}
+
+// GetChainConfig will fetch the network settings based on the given hash.
+func GetChainConfig(db ethdb.Database, hash common.Hash) (*ChainConfig, error) {
+	jsonChainConfig, _ := db.Get(append(configPrefix, hash[:]...))
+	if len(jsonChainConfig) == 0 {
+		return nil, ChainConfigNotFoundErr
+	}
+
+	var config ChainConfig
+	if err := json.Unmarshal(jsonChainConfig, &config); err != nil {
+		return nil, err
+	}
+
+	return &config, nil
+}
diff --git a/core/execution.go b/core/execution.go
index d90dceafc87e23055a1196dc601ebb825279bf63..82143443c79a1cc4730deff41ca3db0baa2f0cab 100644
--- a/core/execution.go
+++ b/core/execution.go
@@ -126,7 +126,7 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
 	// When an error was returned by the EVM or when setting the creation code
 	// above we revert to the snapshot and consume any gas remaining. Additionally
 	// when we're in homestead this also counts for code storage gas errors.
-	if err != nil && (params.IsHomestead(env.BlockNumber()) || err != vm.CodeStoreOutOfGasError) {
+	if err != nil && (env.RuleSet().IsHomestead(env.BlockNumber()) || err != vm.CodeStoreOutOfGasError) {
 		contract.UseGas(contract.Gas)
 
 		env.SetSnapshot(snapshotPreTransfer)
diff --git a/core/genesis.go b/core/genesis.go
index d8c6e9cea36273095247dd46a04a3fded97d05cf..5c69b216c42bb6870d4cfcf620a2535a49caf17f 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -43,15 +43,16 @@ func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block,
 	}
 
 	var genesis struct {
-		Nonce      string
-		Timestamp  string
-		ParentHash string
-		ExtraData  string
-		GasLimit   string
-		Difficulty string
-		Mixhash    string
-		Coinbase   string
-		Alloc      map[string]struct {
+		ChainConfig *ChainConfig
+		Nonce       string
+		Timestamp   string
+		ParentHash  string
+		ExtraData   string
+		GasLimit    string
+		Difficulty  string
+		Mixhash     string
+		Coinbase    string
+		Alloc       map[string]struct {
 			Code    string
 			Storage map[string]string
 			Balance string
@@ -114,6 +115,10 @@ func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block,
 	if err := WriteHeadBlockHash(chainDb, block.Hash()); err != nil {
 		return nil, err
 	}
+	if err := WriteChainConfig(chainDb, block.Hash(), genesis.ChainConfig); err != nil {
+		return nil, err
+	}
+
 	return block, nil
 }
 
diff --git a/core/headerchain.go b/core/headerchain.go
index 255139ddef4b704939db04ac7ab404fe35f5e77d..21fc6e80a25cf114b9dc977118cfd8e296c892b5 100644
--- a/core/headerchain.go
+++ b/core/headerchain.go
@@ -40,6 +40,8 @@ import (
 // It is not thread safe either, the encapsulating chain structures should do
 // the necessary mutex locking/unlocking.
 type HeaderChain struct {
+	config *ChainConfig
+
 	chainDb       ethdb.Database
 	genesisHeader *types.Header
 
@@ -62,7 +64,7 @@ type getHeaderValidatorFn func() HeaderValidator
 //  getValidator should return the parent's validator
 //  procInterrupt points to the parent's interrupt semaphore
 //  wg points to the parent's shutdown wait group
-func NewHeaderChain(chainDb ethdb.Database, getValidator getHeaderValidatorFn, procInterrupt func() bool) (*HeaderChain, error) {
+func NewHeaderChain(chainDb ethdb.Database, config *ChainConfig, getValidator getHeaderValidatorFn, procInterrupt func() bool) (*HeaderChain, error) {
 	headerCache, _ := lru.New(headerCacheLimit)
 	tdCache, _ := lru.New(tdCacheLimit)
 
@@ -73,6 +75,7 @@ func NewHeaderChain(chainDb ethdb.Database, getValidator getHeaderValidatorFn, p
 	}
 
 	hc := &HeaderChain{
+		config:        config,
 		chainDb:       chainDb,
 		headerCache:   headerCache,
 		tdCache:       tdCache,
@@ -436,15 +439,17 @@ func (hc *HeaderChain) SetGenesis(head *types.Header) {
 //
 // headerValidator implements HeaderValidator.
 type headerValidator struct {
-	hc  *HeaderChain // Canonical header chain
-	Pow pow.PoW      // Proof of work used for validating
+	config *ChainConfig
+	hc     *HeaderChain // Canonical header chain
+	Pow    pow.PoW      // Proof of work used for validating
 }
 
 // NewBlockValidator returns a new block validator which is safe for re-use
-func NewHeaderValidator(chain *HeaderChain, pow pow.PoW) HeaderValidator {
+func NewHeaderValidator(config *ChainConfig, chain *HeaderChain, pow pow.PoW) HeaderValidator {
 	return &headerValidator{
-		Pow: pow,
-		hc:  chain,
+		config: config,
+		Pow:    pow,
+		hc:     chain,
 	}
 }
 
@@ -460,5 +465,5 @@ func (v *headerValidator) ValidateHeader(header, parent *types.Header, checkPow
 	if v.hc.HasHeader(header.Hash()) {
 		return nil
 	}
-	return ValidateHeader(v.Pow, header, parent, checkPow, false)
+	return ValidateHeader(v.config, v.Pow, header, parent, checkPow, false)
 }
diff --git a/core/state_processor.go b/core/state_processor.go
index 38cd0e6752e35b9557bc8ad8b65209c158e4c0c2..441f6a7a854dc7a5aad53739fa0507170d9ff840 100644
--- a/core/state_processor.go
+++ b/core/state_processor.go
@@ -16,12 +16,21 @@ var (
 	big32 = big.NewInt(32)
 )
 
+// StateProcessor is a basic Processor, which takes care of transitioning
+// state from one point to another.
+//
+// StateProcessor implements Processor.
 type StateProcessor struct {
-	bc *BlockChain
+	config *ChainConfig
+	bc     *BlockChain
 }
 
-func NewStateProcessor(bc *BlockChain) *StateProcessor {
-	return &StateProcessor{bc}
+// NewStateProcessor initialises a new StateProcessor.
+func NewStateProcessor(config *ChainConfig, bc *BlockChain) *StateProcessor {
+	return &StateProcessor{
+		config: config,
+		bc:     bc,
+	}
 }
 
 // Process processes the state changes according to the Ethereum rules by running
@@ -31,7 +40,7 @@ func NewStateProcessor(bc *BlockChain) *StateProcessor {
 // Process returns the receipts and logs accumulated during the process and
 // returns the amount of gas that was used in the process. If any of the
 // transactions failed to execute due to insufficient gas it will return an error.
-func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg *vm.Config) (types.Receipts, vm.Logs, *big.Int, error) {
+func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, vm.Logs, *big.Int, error) {
 	var (
 		receipts     types.Receipts
 		totalUsedGas = big.NewInt(0)
@@ -43,7 +52,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
 
 	for i, tx := range block.Transactions() {
 		statedb.StartRecord(tx.Hash(), block.Hash(), i)
-		receipt, logs, _, err := ApplyTransaction(p.bc, gp, statedb, header, tx, totalUsedGas, cfg)
+		receipt, logs, _, err := ApplyTransaction(p.config, p.bc, gp, statedb, header, tx, totalUsedGas, cfg)
 		if err != nil {
 			return nil, nil, totalUsedGas, err
 		}
@@ -60,8 +69,8 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
 //
 // ApplyTransactions returns the generated receipts and vm logs during the
 // execution of the state transition phase.
-func ApplyTransaction(bc *BlockChain, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, cfg *vm.Config) (*types.Receipt, vm.Logs, *big.Int, error) {
-	_, gas, err := ApplyMessage(NewEnv(statedb, bc, tx, header, cfg), tx, gp)
+func ApplyTransaction(config *ChainConfig, bc *BlockChain, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, cfg vm.Config) (*types.Receipt, vm.Logs, *big.Int, error) {
+	_, gas, err := ApplyMessage(NewEnv(statedb, config, bc, tx, header, cfg), tx, gp)
 	if err != nil {
 		return nil, nil, nil, err
 	}
diff --git a/core/state_transition.go b/core/state_transition.go
index cc357aacaecdde12c4cbb3b29cc237de360d5eab..c8160424b9439a8f11f8bf0b3f770d3a848d30cf 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -104,8 +104,9 @@ func IntrinsicGas(data []byte, contractCreation, homestead bool) *big.Int {
 	return igas
 }
 
-func ApplyMessage(env vm.Environment, msg Message, gp *GasPool) ([]byte, *big.Int, error) {
-	var st = StateTransition{
+// NewStateTransition initialises and returns a new state transition object.
+func NewStateTransition(env vm.Environment, msg Message, gp *GasPool) *StateTransition {
+	return &StateTransition{
 		gp:         gp,
 		env:        env,
 		msg:        msg,
@@ -116,7 +117,20 @@ func ApplyMessage(env vm.Environment, msg Message, gp *GasPool) ([]byte, *big.In
 		data:       msg.Data(),
 		state:      env.Db(),
 	}
-	return st.transitionDb()
+}
+
+// ApplyMessage computes the new state by applying the given message
+// against the old state within the environment.
+//
+// ApplyMessage returns the bytes returned by any EVM execution (if it took place),
+// the gas used (which includes gas refunds) and an error if it failed. An error always
+// indicates a core error meaning that the message would always fail for that particular
+// state and would never be accepted within a block.
+func ApplyMessage(env vm.Environment, msg Message, gp *GasPool) ([]byte, *big.Int, error) {
+	st := NewStateTransition(env, msg, gp)
+
+	ret, _, gasUsed, err := st.TransitionDb()
+	return ret, gasUsed, err
 }
 
 func (self *StateTransition) from() (vm.Account, error) {
@@ -124,7 +138,7 @@ func (self *StateTransition) from() (vm.Account, error) {
 		f   common.Address
 		err error
 	)
-	if params.IsHomestead(self.env.BlockNumber()) {
+	if self.env.RuleSet().IsHomestead(self.env.BlockNumber()) {
 		f, err = self.msg.From()
 	} else {
 		f, err = self.msg.FromFrontier()
@@ -209,18 +223,19 @@ func (self *StateTransition) preCheck() (err error) {
 	return nil
 }
 
-func (self *StateTransition) transitionDb() (ret []byte, usedGas *big.Int, err error) {
+// TransitionDb will move the state by applying the message against the given environment.
+func (self *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big.Int, err error) {
 	if err = self.preCheck(); err != nil {
 		return
 	}
 	msg := self.msg
 	sender, _ := self.from() // err checked in preCheck
 
-	homestead := params.IsHomestead(self.env.BlockNumber())
+	homestead := self.env.RuleSet().IsHomestead(self.env.BlockNumber())
 	contractCreation := MessageCreatesContract(msg)
 	// Pay intrinsic gas
 	if err = self.useGas(IntrinsicGas(self.data, contractCreation, homestead)); err != nil {
-		return nil, nil, InvalidTxError(err)
+		return nil, nil, nil, InvalidTxError(err)
 	}
 
 	vmenv := self.env
@@ -245,7 +260,7 @@ func (self *StateTransition) transitionDb() (ret []byte, usedGas *big.Int, err e
 	}
 
 	if err != nil && IsValueTransferErr(err) {
-		return nil, nil, InvalidTxError(err)
+		return nil, nil, nil, InvalidTxError(err)
 	}
 
 	// We aren't interested in errors here. Errors returned by the VM are non-consensus errors and therefor shouldn't bubble up
@@ -253,10 +268,12 @@ func (self *StateTransition) transitionDb() (ret []byte, usedGas *big.Int, err e
 		err = nil
 	}
 
+	requiredGas = new(big.Int).Set(self.gasUsed())
+
 	self.refundGas()
 	self.state.AddBalance(self.env.Coinbase(), new(big.Int).Mul(self.gasUsed(), self.gasPrice))
 
-	return ret, self.gasUsed(), err
+	return ret, requiredGas, self.gasUsed(), err
 }
 
 func (self *StateTransition) refundGas() {
diff --git a/core/tx_pool.go b/core/tx_pool.go
index f4e964bf79a1fcd0aaf66da1ab7c0395e602ddb0..e997e8cd010bc0418a57aa16b196efcd415ed35a 100644
--- a/core/tx_pool.go
+++ b/core/tx_pool.go
@@ -30,7 +30,6 @@ import (
 	"github.com/ethereum/go-ethereum/event"
 	"github.com/ethereum/go-ethereum/logger"
 	"github.com/ethereum/go-ethereum/logger/glog"
-	"github.com/ethereum/go-ethereum/params"
 )
 
 var (
@@ -60,6 +59,7 @@ type stateFn func() (*state.StateDB, error)
 // current state) and future transactions. Transactions move between those
 // two states over time as they are received and processed.
 type TxPool struct {
+	config       *ChainConfig
 	quit         chan bool // Quitting channel
 	currentState stateFn   // The state function which will allow us to do some pre checks
 	pendingState *state.ManagedState
@@ -75,8 +75,9 @@ type TxPool struct {
 	homestead bool
 }
 
-func NewTxPool(eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func() *big.Int) *TxPool {
+func NewTxPool(config *ChainConfig, eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func() *big.Int) *TxPool {
 	pool := &TxPool{
+		config:       config,
 		pending:      make(map[common.Hash]*types.Transaction),
 		queue:        make(map[common.Address]map[common.Hash]*types.Transaction),
 		quit:         make(chan bool),
@@ -102,7 +103,7 @@ func (pool *TxPool) eventLoop() {
 		switch ev := ev.Data.(type) {
 		case ChainHeadEvent:
 			pool.mu.Lock()
-			if ev.Block != nil && params.IsHomestead(ev.Block.Number()) {
+			if ev.Block != nil && pool.config.IsHomestead(ev.Block.Number()) {
 				pool.homestead = true
 			}
 
diff --git a/core/tx_pool_test.go b/core/tx_pool_test.go
index fa1a740dc247bfed33e10940e472743f7adb8a12..ed9bea75f093001b4936d7682d7a38f77ddd0cce 100644
--- a/core/tx_pool_test.go
+++ b/core/tx_pool_test.go
@@ -40,7 +40,7 @@ func setupTxPool() (*TxPool, *ecdsa.PrivateKey) {
 
 	var m event.TypeMux
 	key, _ := crypto.GenerateKey()
-	newPool := NewTxPool(&m, func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) })
+	newPool := NewTxPool(testChainConfig(), &m, func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) })
 	newPool.resetState()
 	return newPool, key
 }
diff --git a/core/types.go b/core/types.go
index af9bc567b5a9c3060f011fa4c7172515d0820b35..e2b31643a8eba122ebf0e97a61020b31bebe482d 100644
--- a/core/types.go
+++ b/core/types.go
@@ -61,7 +61,7 @@ type HeaderValidator interface {
 // of gas used in the process and return an error if any of the internal rules
 // failed.
 type Processor interface {
-	Process(block *types.Block, statedb *state.StateDB, cfg *vm.Config) (types.Receipts, vm.Logs, *big.Int, error)
+	Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, vm.Logs, *big.Int, error)
 }
 
 // Backend is an interface defining the basic functionality for an operable node
diff --git a/core/vm/environment.go b/core/vm/environment.go
index 568218edd0717f3bc262f25f137e2f8967886247..747627565e9b51a52054a26d1460dcda4471f875 100644
--- a/core/vm/environment.go
+++ b/core/vm/environment.go
@@ -22,9 +22,17 @@ import (
 	"github.com/ethereum/go-ethereum/common"
 )
 
+// RuleSet is an interface that defines the current rule set during the
+// execution of the EVM instructions (e.g. whether it's homestead)
+type RuleSet interface {
+	IsHomestead(*big.Int) bool
+}
+
 // Environment is an EVM requirement and helper which allows access to outside
 // information such as states.
 type Environment interface {
+	// The current ruleset
+	RuleSet() RuleSet
 	// The state database
 	Db() Database
 	// Creates a restorable snapshot
@@ -53,10 +61,10 @@ type Environment interface {
 	AddLog(*Log)
 	// Type of the VM
 	Vm() Vm
-	// Current calling depth
+	// Get the curret calling depth
 	Depth() int
+	// Set the current calling depth
 	SetDepth(i int)
-
 	// Call another contract
 	Call(me ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error)
 	// Take another's contract code and execute within our own context
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index c4b4339a207b9ace37e90a91ad5d9fa1852bf1d7..942fafde723c05648a20d845953c48e11b882c15 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -520,7 +520,7 @@ func opCreate(instr instruction, pc *uint64, env Environment, contract *Contract
 	// homestead we must check for CodeStoreOutOfGasError (homestead only
 	// rule) and treat as an error, if the ruleset is frontier we must
 	// ignore this error and pretend the operation was successful.
-	if params.IsHomestead(env.BlockNumber()) && suberr == CodeStoreOutOfGasError {
+	if env.RuleSet().IsHomestead(env.BlockNumber()) && suberr == CodeStoreOutOfGasError {
 		stack.push(new(big.Int))
 	} else if suberr != nil && suberr != CodeStoreOutOfGasError {
 		stack.push(new(big.Int))
diff --git a/core/vm/jit.go b/core/vm/jit.go
index 71ffcf0f69a0d12493d6bdea6f59b4f3e62d8592..ac2083f54cfb710740b5b6db7fec83cd21d1910e 100644
--- a/core/vm/jit.go
+++ b/core/vm/jit.go
@@ -30,27 +30,24 @@ import (
 	"github.com/hashicorp/golang-lru"
 )
 
+// progStatus is the type for the JIT program status.
 type progStatus int32
 
 const (
-	progUnknown progStatus = iota
-	progCompile
-	progReady
-	progError
+	progUnknown progStatus = iota // unknown status
+	progCompile                   // compile status
+	progReady                     // ready for use status
+	progError                     // error status (usually caused during compilation)
 
-	defaultJitMaxCache int = 64
+	defaultJitMaxCache int = 64 // maximum amount of jit cached programs
 )
 
-var (
-	EnableJit   bool // Enables the JIT VM
-	ForceJit    bool // Force the JIT, skip byte VM
-	MaxProgSize int  // Max cache size for JIT Programs
-)
+var MaxProgSize int // Max cache size for JIT programs
 
-var programs *lru.Cache
+var programs *lru.Cache // lru cache for the JIT programs.
 
 func init() {
-	programs, _ = lru.New(defaultJitMaxCache)
+	SetJITCacheSize(defaultJitMaxCache)
 }
 
 // SetJITCacheSize recreates the program cache with the max given size. Setting
@@ -322,7 +319,7 @@ func runProgram(program *Program, pcstart uint64, mem *Memory, stack *stack, env
 		}()
 	}
 
-	homestead := params.IsHomestead(env.BlockNumber())
+	homestead := env.RuleSet().IsHomestead(env.BlockNumber())
 	for pc < uint64(len(program.instructions)) {
 		instrCount++
 
diff --git a/core/vm/jit_test.go b/core/vm/jit_test.go
index 43b1dee2ab7a9042ff9b4069938a3465f5cb2032..c503a3a8167f02e9a3b33d3b183f16b93cf3644b 100644
--- a/core/vm/jit_test.go
+++ b/core/vm/jit_test.go
@@ -84,7 +84,7 @@ func TestCompiling(t *testing.T) {
 func TestResetInput(t *testing.T) {
 	var sender account
 
-	env := NewEnv()
+	env := NewEnv(false, true)
 	contract := NewContract(sender, sender, big.NewInt(100), big.NewInt(10000), big.NewInt(0))
 	contract.CodeAddr = &common.Address{}
 
@@ -143,10 +143,7 @@ func runVmBench(test vmBench, b *testing.B) {
 	if test.precompile && !test.forcejit {
 		NewProgram(test.code)
 	}
-	env := NewEnv()
-
-	EnableJit = !test.nojit
-	ForceJit = test.forcejit
+	env := NewEnv(test.nojit, test.forcejit)
 
 	b.ResetTimer()
 
@@ -168,12 +165,16 @@ type Env struct {
 	evm      *EVM
 }
 
-func NewEnv() *Env {
+func NewEnv(noJit, forceJit bool) *Env {
 	env := &Env{gasLimit: big.NewInt(10000), depth: 0}
-	env.evm = New(env, nil)
+	env.evm = New(env, Config{
+		EnableJit: !noJit,
+		ForceJit:  forceJit,
+	})
 	return env
 }
 
+func (self *Env) RuleSet() RuleSet       { return ruleSet{new(big.Int)} }
 func (self *Env) Vm() Vm                 { return self.evm }
 func (self *Env) Origin() common.Address { return common.Address{} }
 func (self *Env) BlockNumber() *big.Int  { return big.NewInt(0) }
diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go
index 8297d3e1d1e9ab0f891cbb81ac0d7204f9d001ed..2c379667937ba177eb3bfb457f3835e7e0de50b9 100644
--- a/core/vm/jump_table.go
+++ b/core/vm/jump_table.go
@@ -1,10 +1,6 @@
 package vm
 
-import (
-	"math/big"
-
-	"github.com/ethereum/go-ethereum/params"
-)
+import "math/big"
 
 type jumpPtr struct {
 	fn    instrFn
@@ -13,12 +9,12 @@ type jumpPtr struct {
 
 type vmJumpTable [256]jumpPtr
 
-func newJumpTable(blockNumber *big.Int) vmJumpTable {
+func newJumpTable(ruleset RuleSet, blockNumber *big.Int) vmJumpTable {
 	var jumpTable vmJumpTable
 
 	// when initialising a new VM execution we must first check the homestead
 	// changes.
-	if params.IsHomestead(blockNumber) {
+	if ruleset.IsHomestead(blockNumber) {
 		jumpTable[DELEGATECALL] = jumpPtr{opDelegateCall, true}
 	}
 
diff --git a/core/vm/jump_table_test.go b/core/vm/jump_table_test.go
index 2ed1b26fc7593d2e68dce826cc0d7e3b307acfe1..2386a7525e3977d55e182a10324ddbd5dc767477 100644
--- a/core/vm/jump_table_test.go
+++ b/core/vm/jump_table_test.go
@@ -3,20 +3,16 @@ package vm
 import (
 	"math/big"
 	"testing"
-
-	"github.com/ethereum/go-ethereum/params"
 )
 
 func TestInit(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1)
-
-	jumpTable := newJumpTable(big.NewInt(0))
+	jumpTable := newJumpTable(ruleSet{big.NewInt(1)}, big.NewInt(0))
 	if jumpTable[DELEGATECALL].valid {
 		t.Error("Expected DELEGATECALL not to be present")
 	}
 
 	for _, n := range []int64{1, 2, 100} {
-		jumpTable := newJumpTable(big.NewInt(n))
+		jumpTable := newJumpTable(ruleSet{big.NewInt(1)}, big.NewInt(n))
 		if !jumpTable[DELEGATECALL].valid {
 			t.Error("Expected DELEGATECALL to be present for block", n)
 		}
diff --git a/core/vm/logger.go b/core/vm/logger.go
index 8d333dfd255a1d353553853bc96a3f96d8f58b10..cbdc8a7447ded86317787d7d0b3a4c7957783e7e 100644
--- a/core/vm/logger.go
+++ b/core/vm/logger.go
@@ -89,7 +89,7 @@ func newLogger(cfg LogConfig, env Environment) *Logger {
 // captureState logs a new structured log message and pushes it out to the environment
 //
 // captureState also tracks SSTORE ops to track dirty values.
-func (l *Logger) captureState(pc uint64, op OpCode, gas, cost *big.Int, memory *Memory, stack *stack, contract *Contract, err error) {
+func (l *Logger) captureState(pc uint64, op OpCode, gas, cost *big.Int, memory *Memory, stack *stack, contract *Contract, depth int, err error) {
 	// short circuit if no log collector is present
 	if l.cfg.Collector == nil {
 		return
diff --git a/core/vm/logger_test.go b/core/vm/logger_test.go
index 77fee2c6492fb96946b90e6be0827f091b26ae43..1445698659b966769163074b33b22ffd6792c993 100644
--- a/core/vm/logger_test.go
+++ b/core/vm/logger_test.go
@@ -47,7 +47,7 @@ type dummyEnv struct {
 
 func newDummyEnv(ref *dummyContractRef) *dummyEnv {
 	return &dummyEnv{
-		Env: NewEnv(),
+		Env: NewEnv(true, false),
 		ref: ref,
 	}
 }
@@ -58,7 +58,7 @@ func (d dummyEnv) AddStructLog(StructLog) {}
 
 func TestStoreCapture(t *testing.T) {
 	var (
-		env      = NewEnv()
+		env      = NewEnv(true, false)
 		logger   = newLogger(LogConfig{Collector: env}, env)
 		mem      = NewMemory()
 		stack    = newstack()
@@ -69,7 +69,7 @@ func TestStoreCapture(t *testing.T) {
 
 	var index common.Hash
 
-	logger.captureState(0, SSTORE, new(big.Int), new(big.Int), mem, stack, contract, nil)
+	logger.captureState(0, SSTORE, new(big.Int), new(big.Int), mem, stack, contract, 0, nil)
 	if len(logger.changedValues[contract.Address()]) == 0 {
 		t.Fatalf("expected exactly 1 changed value on address %x, got %d", contract.Address(), len(logger.changedValues[contract.Address()]))
 	}
@@ -91,13 +91,13 @@ func TestStorageCapture(t *testing.T) {
 		stack    = newstack()
 	)
 
-	logger.captureState(0, STOP, new(big.Int), new(big.Int), mem, stack, contract, nil)
+	logger.captureState(0, STOP, new(big.Int), new(big.Int), mem, stack, contract, 0, nil)
 	if ref.calledForEach {
 		t.Error("didn't expect for each to be called")
 	}
 
 	logger = newLogger(LogConfig{Collector: env, FullStorage: true}, env)
-	logger.captureState(0, STOP, new(big.Int), new(big.Int), mem, stack, contract, nil)
+	logger.captureState(0, STOP, new(big.Int), new(big.Int), mem, stack, contract, 0, nil)
 	if !ref.calledForEach {
 		t.Error("expected for each to be called")
 	}
diff --git a/core/vm/runtime/env.go b/core/vm/runtime/env.go
index ce64d711765ec11bde599c0ee94c6ca24c671065..1e943940bdab95edf457b262c55220156f65a444 100644
--- a/core/vm/runtime/env.go
+++ b/core/vm/runtime/env.go
@@ -27,8 +27,9 @@ import (
 
 // Env is a basic runtime environment required for running the EVM.
 type Env struct {
-	depth int
-	state *state.StateDB
+	ruleSet vm.RuleSet
+	depth   int
+	state   *state.StateDB
 
 	origin   common.Address
 	coinbase common.Address
@@ -48,6 +49,7 @@ type Env struct {
 // NewEnv returns a new vm.Environment
 func NewEnv(cfg *Config, state *state.StateDB) vm.Environment {
 	env := &Env{
+		ruleSet:    cfg.RuleSet,
 		state:      state,
 		origin:     cfg.Origin,
 		coinbase:   cfg.Coinbase,
@@ -56,7 +58,7 @@ func NewEnv(cfg *Config, state *state.StateDB) vm.Environment {
 		difficulty: cfg.Difficulty,
 		gasLimit:   cfg.GasLimit,
 	}
-	env.evm = vm.New(env, &vm.Config{
+	env.evm = vm.New(env, vm.Config{
 		Debug:     cfg.Debug,
 		EnableJit: !cfg.DisableJit,
 		ForceJit:  !cfg.DisableJit,
@@ -77,6 +79,7 @@ func (self *Env) AddStructLog(log vm.StructLog) {
 	self.logs = append(self.logs, log)
 }
 
+func (self *Env) RuleSet() vm.RuleSet      { return self.ruleSet }
 func (self *Env) Vm() vm.Vm                { return self.evm }
 func (self *Env) Origin() common.Address   { return self.origin }
 func (self *Env) BlockNumber() *big.Int    { return self.number }
diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go
index f88a201702f7bc0aac9b7017a1b7a11195092ecf..553864a83422f9829dceb48ebb54aec058413a9d 100644
--- a/core/vm/runtime/runtime.go
+++ b/core/vm/runtime/runtime.go
@@ -22,13 +22,20 @@ import (
 
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/core/state"
+	"github.com/ethereum/go-ethereum/core/vm"
 	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/ethdb"
 )
 
+// The default, always homestead, rule set for the vm env
+type ruleSet struct{}
+
+func (ruleSet) IsHomestead(*big.Int) bool { return true }
+
 // Config is a basic type specifying certain configuration flags for running
 // the EVM.
 type Config struct {
+	RuleSet     vm.RuleSet
 	Difficulty  *big.Int
 	Origin      common.Address
 	Coinbase    common.Address
@@ -46,6 +53,10 @@ type Config struct {
 
 // sets defaults on the config
 func setDefaults(cfg *Config) {
+	if cfg.RuleSet == nil {
+		cfg.RuleSet = ruleSet{}
+	}
+
 	if cfg.Difficulty == nil {
 		cfg.Difficulty = new(big.Int)
 	}
diff --git a/core/vm/util_test.go b/core/vm/util_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..3da742bfa08e3834d9855026bffd455b9f371884
--- /dev/null
+++ b/core/vm/util_test.go
@@ -0,0 +1,9 @@
+package vm
+
+import "math/big"
+
+type ruleSet struct {
+	hs *big.Int
+}
+
+func (r ruleSet) IsHomestead(n *big.Int) bool { return n.Cmp(r.hs) >= 0 }
diff --git a/core/vm/vm.go b/core/vm/vm.go
index f72c853a2566c674258eb8af57987298da61ba2c..0f93715d6f34685bfb6c260d7047db3867a4f0b9 100644
--- a/core/vm/vm.go
+++ b/core/vm/vm.go
@@ -43,18 +43,13 @@ type Config struct {
 type EVM struct {
 	env       Environment
 	jumpTable vmJumpTable
-	cfg       *Config
+	cfg       Config
 
 	logger *Logger
 }
 
 // New returns a new instance of the EVM.
-func New(env Environment, cfg *Config) *EVM {
-	// initialise a default config if none is present
-	if cfg == nil {
-		cfg = new(Config)
-	}
-
+func New(env Environment, cfg Config) *EVM {
 	var logger *Logger
 	if cfg.Debug {
 		logger = newLogger(cfg.Logger, env)
@@ -62,7 +57,7 @@ func New(env Environment, cfg *Config) *EVM {
 
 	return &EVM{
 		env:       env,
-		jumpTable: newJumpTable(env.BlockNumber()),
+		jumpTable: newJumpTable(env.RuleSet(), env.BlockNumber()),
 		cfg:       cfg,
 		logger:    logger,
 	}
@@ -154,7 +149,7 @@ func (evm *EVM) Run(contract *Contract, input []byte) (ret []byte, err error) {
 	// User defer pattern to check for an error and, based on the error being nil or not, use all gas and return.
 	defer func() {
 		if err != nil && evm.cfg.Debug {
-			evm.logger.captureState(pc, op, contract.Gas, cost, mem, stack, contract, err)
+			evm.logger.captureState(pc, op, contract.Gas, cost, mem, stack, contract, evm.env.Depth(), err)
 		}
 	}()
 
@@ -196,7 +191,7 @@ func (evm *EVM) Run(contract *Contract, input []byte) (ret []byte, err error) {
 		mem.Resize(newMemSize.Uint64())
 		// Add a log message
 		if evm.cfg.Debug {
-			evm.logger.captureState(pc, op, contract.Gas, cost, mem, stack, contract, nil)
+			evm.logger.captureState(pc, op, contract.Gas, cost, mem, stack, contract, evm.env.Depth(), nil)
 		}
 
 		if opPtr := evm.jumpTable[op]; opPtr.valid {
diff --git a/core/vm/vm_jit_fake.go b/core/vm/vm_jit_fake.go
index b26cf1ad0d4e2cde0eaf13986df95b5669bf7ff6..4fa98ccd9cf94aff4b540056b177be276572def7 100644
--- a/core/vm/vm_jit_fake.go
+++ b/core/vm/vm_jit_fake.go
@@ -22,5 +22,5 @@ import "fmt"
 
 func NewJitVm(env Environment) VirtualMachine {
 	fmt.Printf("Warning! EVM JIT not enabled.\n")
-	return New(env, nil)
+	return New(env, Config{})
 }
diff --git a/core/vm_env.go b/core/vm_env.go
index 880baa7b0f1d362c7902b843292e4640bcb1d30d..f50140c6811a1988bfbc399795ec209adcbdffab 100644
--- a/core/vm_env.go
+++ b/core/vm_env.go
@@ -41,30 +41,26 @@ func GetHashFn(ref common.Hash, chain *BlockChain) func(n uint64) common.Hash {
 }
 
 type VMEnv struct {
-	state *state.StateDB // State to use for executing
-	evm   *vm.EVM        // The Ethereum Virtual Machine
-	depth int            // Current execution depth
-	msg   Message        // Message appliod
+	chainConfig *ChainConfig   // Chain configuration
+	state       *state.StateDB // State to use for executing
+	evm         *vm.EVM        // The Ethereum Virtual Machine
+	depth       int            // Current execution depth
+	msg         Message        // Message appliod
 
 	header    *types.Header            // Header information
 	chain     *BlockChain              // Blockchain handle
 	logs      []vm.StructLog           // Logs for the custom structured logger
 	getHashFn func(uint64) common.Hash // getHashFn callback is used to retrieve block hashes
-
 }
 
-func NewEnv(state *state.StateDB, chain *BlockChain, msg Message, header *types.Header, cfg *vm.Config) *VMEnv {
+func NewEnv(state *state.StateDB, chainConfig *ChainConfig, chain *BlockChain, msg Message, header *types.Header, cfg vm.Config) *VMEnv {
 	env := &VMEnv{
-		chain:     chain,
-		state:     state,
-		header:    header,
-		msg:       msg,
-		getHashFn: GetHashFn(header.ParentHash, chain),
-	}
-
-	// initialise a default config if none present
-	if cfg == nil {
-		cfg = new(vm.Config)
+		chainConfig: chainConfig,
+		chain:       chain,
+		state:       state,
+		header:      header,
+		msg:         msg,
+		getHashFn:   GetHashFn(header.ParentHash, chain),
 	}
 
 	// if no log collector is present set self as the collector
@@ -76,6 +72,7 @@ func NewEnv(state *state.StateDB, chain *BlockChain, msg Message, header *types.
 	return env
 }
 
+func (self *VMEnv) RuleSet() vm.RuleSet      { return self.chainConfig }
 func (self *VMEnv) Vm() vm.Vm                { return self.evm }
 func (self *VMEnv) Origin() common.Address   { f, _ := self.msg.From(); return f }
 func (self *VMEnv) BlockNumber() *big.Int    { return self.header.Number }
diff --git a/eth/api.go b/eth/api.go
index 4a03a0940ea889238e4450fe32e410c96a23fc2c..af03c096dc5a1f849d095fe9638602280556e2b8 100644
--- a/eth/api.go
+++ b/eth/api.go
@@ -456,6 +456,7 @@ func (s *PrivateAccountAPI) LockAccount(addr common.Address) bool {
 // PublicBlockChainAPI provides an API to access the Ethereum blockchain.
 // It offers only methods that operate on public data that is freely available to anyone.
 type PublicBlockChainAPI struct {
+	config   *core.ChainConfig
 	bc       *core.BlockChain
 	chainDb  ethdb.Database
 	eventMux *event.TypeMux
@@ -464,8 +465,8 @@ type PublicBlockChainAPI struct {
 }
 
 // NewPublicBlockChainAPI creates a new Etheruem blockchain API.
-func NewPublicBlockChainAPI(bc *core.BlockChain, m *miner.Miner, chainDb ethdb.Database, eventMux *event.TypeMux, am *accounts.Manager) *PublicBlockChainAPI {
-	return &PublicBlockChainAPI{bc: bc, miner: m, chainDb: chainDb, eventMux: eventMux, am: am}
+func NewPublicBlockChainAPI(config *core.ChainConfig, bc *core.BlockChain, m *miner.Miner, chainDb ethdb.Database, eventMux *event.TypeMux, am *accounts.Manager) *PublicBlockChainAPI {
+	return &PublicBlockChainAPI{config: config, bc: bc, miner: m, chainDb: chainDb, eventMux: eventMux, am: am}
 }
 
 // BlockNumber returns the block number of the chain head.
@@ -670,14 +671,14 @@ func (s *PublicBlockChainAPI) doCall(args CallArgs, blockNr rpc.BlockNumber) (st
 	}
 
 	// Execute the call and return
-	vmenv := core.NewEnv(stateDb, s.bc, msg, block.Header(), nil)
+	vmenv := core.NewEnv(stateDb, s.config, s.bc, msg, block.Header(), s.config.VmConfig)
 	gp := new(core.GasPool).AddGas(common.MaxBig)
 
-	res, gas, err := core.ApplyMessage(vmenv, msg, gp)
+	res, requiredGas, _, err := core.NewStateTransition(vmenv, msg, gp).TransitionDb()
 	if len(res) == 0 { // backwards compatibility
-		return "0x", gas, err
+		return "0x", requiredGas, err
 	}
-	return common.ToHex(res), gas, err
+	return common.ToHex(res), requiredGas, err
 }
 
 // Call executes the given transaction on the state for the given block number.
@@ -1501,13 +1502,14 @@ func (api *PublicDebugAPI) SeedHash(number uint64) (string, error) {
 // PrivateDebugAPI is the collection of Etheruem APIs exposed over the private
 // debugging endpoint.
 type PrivateDebugAPI struct {
-	eth *Ethereum
+	config *core.ChainConfig
+	eth    *Ethereum
 }
 
 // NewPrivateDebugAPI creates a new API definition for the private debug methods
 // of the Ethereum service.
-func NewPrivateDebugAPI(eth *Ethereum) *PrivateDebugAPI {
-	return &PrivateDebugAPI{eth: eth}
+func NewPrivateDebugAPI(config *core.ChainConfig, eth *Ethereum) *PrivateDebugAPI {
+	return &PrivateDebugAPI{config: config, eth: eth}
 }
 
 // BlockTraceResults is the returned value when replaying a block to check for
@@ -1601,7 +1603,7 @@ func (api *PrivateDebugAPI) traceBlock(block *types.Block, config vm.Config) (bo
 	config.Debug = true // make sure debug is set.
 	config.Logger.Collector = collector
 
-	if err := core.ValidateHeader(blockchain.AuxValidator(), block.Header(), blockchain.GetHeader(block.ParentHash()), true, false); err != nil {
+	if err := core.ValidateHeader(api.config, blockchain.AuxValidator(), block.Header(), blockchain.GetHeader(block.ParentHash()), true, false); err != nil {
 		return false, collector.traces, err
 	}
 	statedb, err := state.New(blockchain.GetBlock(block.ParentHash()).Root(), api.eth.ChainDb())
@@ -1609,7 +1611,7 @@ func (api *PrivateDebugAPI) traceBlock(block *types.Block, config vm.Config) (bo
 		return false, collector.traces, err
 	}
 
-	receipts, _, usedGas, err := processor.Process(block, statedb, &config)
+	receipts, _, usedGas, err := processor.Process(block, statedb, config)
 	if err != nil {
 		return false, collector.traces, err
 	}
@@ -1731,7 +1733,7 @@ func (s *PrivateDebugAPI) TraceTransaction(txHash common.Hash, logger vm.LogConf
 		data:     tx.Data(),
 	}
 
-	vmenv := core.NewEnv(stateDb, s.eth.BlockChain(), msg, block.Header(), &vm.Config{
+	vmenv := core.NewEnv(stateDb, s.config, s.eth.BlockChain(), msg, block.Header(), vm.Config{
 		Debug:  true,
 		Logger: logger,
 	})
@@ -1788,7 +1790,9 @@ func (s *PublicBlockChainAPI) TraceCall(args CallArgs, blockNr rpc.BlockNumber)
 	}
 
 	// Execute the call and return
-	vmenv := core.NewEnv(stateDb, s.bc, msg, block.Header(), nil)
+	vmenv := core.NewEnv(stateDb, s.config, s.bc, msg, block.Header(), vm.Config{
+		Debug: true,
+	})
 	gp := new(core.GasPool).AddGas(common.MaxBig)
 
 	ret, gas, err := core.ApplyMessage(vmenv, msg, gp)
diff --git a/eth/backend.go b/eth/backend.go
index 4f3e11a50c53c8d3cb333084002642102a18a962..3c3440a53d1c517a4e7cd32fc69f3ee398e824d3 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -63,6 +63,8 @@ var (
 )
 
 type Config struct {
+	ChainConfig *core.ChainConfig // chain configuration
+
 	NetworkId int    // Network ID to use for selecting peers to connect to
 	Genesis   string // Genesis JSON to seed the chain database with
 	FastSync  bool   // Enables the state download based fast synchronisation algorithm
@@ -100,6 +102,7 @@ type Config struct {
 }
 
 type Ethereum struct {
+	chainConfig *core.ChainConfig
 	// Channel for shutting down the ethereum
 	shutdownChan chan bool
 
@@ -166,12 +169,17 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
 
 	// Load up any custom genesis block if requested
 	if len(config.Genesis) > 0 {
+		// Using println instead of glog to make sure it **always** displays regardless of
+		// verbosity settings.
+		common.PrintDepricationWarning("--genesis is deprecated. Switch to use 'geth init /path/to/file'")
+
 		block, err := core.WriteGenesisBlock(chainDb, strings.NewReader(config.Genesis))
 		if err != nil {
 			return nil, err
 		}
 		glog.V(logger.Info).Infof("Successfully wrote custom genesis block: %x", block.Hash())
 	}
+
 	// Load up a test setup if directly injected
 	if config.TestGenesisState != nil {
 		chainDb = config.TestGenesisState
@@ -227,26 +235,38 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
 	default:
 		eth.pow = ethash.New()
 	}
-	//genesis := core.GenesisBlock(uint64(config.GenesisNonce), stateDb)
-	eth.blockchain, err = core.NewBlockChain(chainDb, eth.pow, eth.EventMux())
-	eth.blockchain.SetConfig(&vm.Config{
+
+	// load the genesis block or write a new one if no genesis
+	// block is prenent in the database.
+	genesis := core.GetBlock(chainDb, core.GetCanonicalHash(chainDb, 0))
+	if genesis == nil {
+		genesis, err = core.WriteDefaultGenesisBlock(chainDb)
+		if err != nil {
+			return nil, err
+		}
+		glog.V(logger.Info).Infoln("WARNING: Wrote default ethereum genesis block")
+	}
+
+	eth.chainConfig = config.ChainConfig
+	eth.chainConfig.VmConfig = vm.Config{
 		EnableJit: config.EnableJit,
 		ForceJit:  config.ForceJit,
-	})
+	}
 
+	eth.blockchain, err = core.NewBlockChain(chainDb, eth.chainConfig, eth.pow, eth.EventMux())
 	if err != nil {
 		if err == core.ErrNoGenesis {
-			return nil, fmt.Errorf(`Genesis block not found. Please supply a genesis block with the "--genesis /path/to/file" argument`)
+			return nil, fmt.Errorf(`No chain found. Please initialise a new chain using the "init" subcommand.`)
 		}
 		return nil, err
 	}
-	newPool := core.NewTxPool(eth.EventMux(), eth.blockchain.State, eth.blockchain.GasLimit)
+	newPool := core.NewTxPool(eth.chainConfig, eth.EventMux(), eth.blockchain.State, eth.blockchain.GasLimit)
 	eth.txPool = newPool
 
-	if eth.protocolManager, err = NewProtocolManager(config.FastSync, config.NetworkId, eth.eventMux, eth.txPool, eth.pow, eth.blockchain, chainDb); err != nil {
+	if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.FastSync, config.NetworkId, eth.eventMux, eth.txPool, eth.pow, eth.blockchain, chainDb); err != nil {
 		return nil, err
 	}
-	eth.miner = miner.New(eth, eth.EventMux(), eth.pow)
+	eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.pow)
 	eth.miner.SetGasPrice(config.GasPrice)
 	eth.miner.SetExtra(config.ExtraData)
 
@@ -275,7 +295,7 @@ func (s *Ethereum) APIs() []rpc.API {
 		}, {
 			Namespace: "eth",
 			Version:   "1.0",
-			Service:   NewPublicBlockChainAPI(s.BlockChain(), s.Miner(), s.ChainDb(), s.EventMux(), s.AccountManager()),
+			Service:   NewPublicBlockChainAPI(s.chainConfig, s.BlockChain(), s.Miner(), s.ChainDb(), s.EventMux(), s.AccountManager()),
 			Public:    true,
 		}, {
 			Namespace: "eth",
@@ -319,7 +339,7 @@ func (s *Ethereum) APIs() []rpc.API {
 		}, {
 			Namespace: "debug",
 			Version:   "1.0",
-			Service:   NewPrivateDebugAPI(s),
+			Service:   NewPrivateDebugAPI(s.chainConfig, s),
 		}, {
 			Namespace: "net",
 			Version:   "1.0",
@@ -328,7 +348,7 @@ func (s *Ethereum) APIs() []rpc.API {
 		}, {
 			Namespace: "admin",
 			Version:   "1.0",
-			Service:   ethreg.NewPrivateRegistarAPI(s.BlockChain(), s.ChainDb(), s.TxPool(), s.AccountManager()),
+			Service:   ethreg.NewPrivateRegistarAPI(s.chainConfig, s.BlockChain(), s.ChainDb(), s.TxPool(), s.AccountManager()),
 		},
 	}
 }
diff --git a/eth/handler.go b/eth/handler.go
index 2c5cae479f5cd8eca84af1911d6873652c9c8563..135de374961cac8eb1065302a8e7a51d79c4117a 100644
--- a/eth/handler.go
+++ b/eth/handler.go
@@ -86,7 +86,7 @@ type ProtocolManager struct {
 
 // NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
 // with the ethereum network.
-func NewProtocolManager(fastSync bool, networkId int, mux *event.TypeMux, txpool txPool, pow pow.PoW, blockchain *core.BlockChain, chaindb ethdb.Database) (*ProtocolManager, error) {
+func NewProtocolManager(config *core.ChainConfig, fastSync bool, networkId int, mux *event.TypeMux, txpool txPool, pow pow.PoW, blockchain *core.BlockChain, chaindb ethdb.Database) (*ProtocolManager, error) {
 	// Figure out whether to allow fast sync or not
 	if fastSync && blockchain.CurrentBlock().NumberU64() > 0 {
 		glog.V(logger.Info).Infof("blockchain not empty, fast sync disabled")
@@ -144,7 +144,7 @@ func NewProtocolManager(fastSync bool, networkId int, mux *event.TypeMux, txpool
 		manager.removePeer)
 
 	validator := func(block *types.Block, parent *types.Block) error {
-		return core.ValidateHeader(pow, block.Header(), parent.Header(), true, false)
+		return core.ValidateHeader(config, pow, block.Header(), parent.Header(), true, false)
 	}
 	heighter := func() uint64 {
 		return blockchain.CurrentBlock().NumberU64()
diff --git a/eth/helper_test.go b/eth/helper_test.go
index bbd1fb81825eb56f2ac1acab716e49e08d3b7d65..13de1867059003a06ebc554e40d4c989fa8ed2f6 100644
--- a/eth/helper_test.go
+++ b/eth/helper_test.go
@@ -34,13 +34,15 @@ func newTestProtocolManager(fastSync bool, blocks int, generator func(int, *core
 		pow           = new(core.FakePow)
 		db, _         = ethdb.NewMemDatabase()
 		genesis       = core.WriteGenesisBlockForTesting(db, core.GenesisAccount{testBankAddress, testBankFunds})
-		blockchain, _ = core.NewBlockChain(db, pow, evmux)
+		chainConfig   = &core.ChainConfig{HomesteadBlock: big.NewInt(0)} // homestead set to 0 because of chain maker
+		blockchain, _ = core.NewBlockChain(db, chainConfig, pow, evmux)
 	)
 	chain, _ := core.GenerateChain(genesis, db, blocks, generator)
 	if _, err := blockchain.InsertChain(chain); err != nil {
 		panic(err)
 	}
-	pm, err := NewProtocolManager(fastSync, NetworkId, evmux, &testTxPool{added: newtx}, pow, blockchain, db)
+
+	pm, err := NewProtocolManager(chainConfig, fastSync, NetworkId, evmux, &testTxPool{added: newtx}, pow, blockchain, db)
 	if err != nil {
 		return nil, err
 	}
diff --git a/miner/miner.go b/miner/miner.go
index e52cefaab22990a1116f9397fe43cfc010bd5a26..7cc25cdf7f4a73606e580442536611037d4b5afb 100644
--- a/miner/miner.go
+++ b/miner/miner.go
@@ -51,8 +51,8 @@ type Miner struct {
 	shouldStart int32 // should start indicates whether we should start after sync
 }
 
-func New(eth core.Backend, mux *event.TypeMux, pow pow.PoW) *Miner {
-	miner := &Miner{eth: eth, mux: mux, pow: pow, worker: newWorker(common.Address{}, eth), canStart: 1}
+func New(eth core.Backend, config *core.ChainConfig, mux *event.TypeMux, pow pow.PoW) *Miner {
+	miner := &Miner{eth: eth, mux: mux, pow: pow, worker: newWorker(config, common.Address{}, eth), canStart: 1}
 	go miner.update()
 
 	return miner
diff --git a/miner/worker.go b/miner/worker.go
index b3ddf9707a378f868222098c32e4e2b5263824c7..c45945b87cae12bb1a631b105384d0ac869a3db4 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -61,6 +61,7 @@ type uint64RingBuffer struct {
 // environment is the workers current environment and holds
 // all of the current state information
 type Work struct {
+	config             *core.ChainConfig
 	state              *state.StateDB // apply state changes here
 	ancestors          *set.Set       // ancestor set (used for checking uncle parent validity)
 	family             *set.Set       // family set (used for checking uncle invalidity)
@@ -89,6 +90,8 @@ type Result struct {
 
 // worker is the main object which takes care of applying messages to the new state
 type worker struct {
+	config *core.ChainConfig
+
 	mu sync.Mutex
 
 	agents map[Agent]struct{}
@@ -122,8 +125,9 @@ type worker struct {
 	fullValidation bool
 }
 
-func newWorker(coinbase common.Address, eth core.Backend) *worker {
+func newWorker(config *core.ChainConfig, coinbase common.Address, eth core.Backend) *worker {
 	worker := &worker{
+		config:         config,
 		eth:            eth,
 		mux:            eth.EventMux(),
 		chainDb:        eth.ChainDb(),
@@ -285,7 +289,7 @@ func (self *worker) wait() {
 				}
 
 				auxValidator := self.eth.BlockChain().AuxValidator()
-				if err := core.ValidateHeader(auxValidator, block.Header(), parent.Header(), true, false); err != nil && err != core.BlockFutureErr {
+				if err := core.ValidateHeader(self.config, auxValidator, block.Header(), parent.Header(), true, false); err != nil && err != core.BlockFutureErr {
 					glog.V(logger.Error).Infoln("Invalid header on mined block:", err)
 					continue
 				}
@@ -371,6 +375,7 @@ func (self *worker) makeCurrent(parent *types.Block, header *types.Header) error
 		return err
 	}
 	work := &Work{
+		config:    self.config,
 		state:     state,
 		ancestors: set.New(),
 		family:    set.New(),
@@ -470,7 +475,7 @@ func (self *worker) commitNewWork() {
 	header := &types.Header{
 		ParentHash: parent.Hash(),
 		Number:     num.Add(num, common.Big1),
-		Difficulty: core.CalcDifficulty(uint64(tstamp), parent.Time().Uint64(), parent.Number(), parent.Difficulty()),
+		Difficulty: core.CalcDifficulty(self.config, uint64(tstamp), parent.Time().Uint64(), parent.Number(), parent.Difficulty()),
 		GasLimit:   core.CalcGasLimit(parent),
 		GasUsed:    new(big.Int),
 		Coinbase:   self.coinbase,
@@ -657,7 +662,7 @@ func (env *Work) commitTransactions(mux *event.TypeMux, transactions types.Trans
 
 func (env *Work) commitTransaction(tx *types.Transaction, bc *core.BlockChain, gp *core.GasPool) (error, vm.Logs) {
 	snap := env.state.Copy()
-	receipt, logs, _, err := core.ApplyTransaction(bc, gp, env.state, env.header, tx, env.header.GasUsed, nil)
+	receipt, logs, _, err := core.ApplyTransaction(env.config, bc, gp, env.state, env.header, tx, env.header.GasUsed, env.config.VmConfig)
 	if err != nil {
 		env.state.Set(snap)
 		return err, nil
diff --git a/params/protocol_params.go b/params/protocol_params.go
index 45a9a2549e8a1ffc2c64c98155f693b6c810267e..2dfc251b6374e31165256dbbcb9ec65c59120af0 100644
--- a/params/protocol_params.go
+++ b/params/protocol_params.go
@@ -40,8 +40,9 @@ var (
 	EcrecoverGas           = big.NewInt(3000)   //
 	Sha256WordGas          = big.NewInt(12)     //
 
-	MinGasLimit     = big.NewInt(5000)    // Minimum the gas limit may ever be.
-	GenesisGasLimit = big.NewInt(4712388) // Gas limit of the Genesis block.
+	MinGasLimit     = big.NewInt(5000)                  // Minimum the gas limit may ever be.
+	GenesisGasLimit = big.NewInt(4712388)               // Gas limit of the Genesis block.
+	TargetGasLimit  = new(big.Int).Set(GenesisGasLimit) // The artificial target
 
 	Sha3Gas              = big.NewInt(30)     // Once per SHA3 operation.
 	Sha256Gas            = big.NewInt(60)     //
diff --git a/params/util.go b/params/util.go
index 6a49a20135cb58c4d9b23c3e74a385abebc97250..b37bc79b21d3c5c512333784ff65b35dd99c910c 100644
--- a/params/util.go
+++ b/params/util.go
@@ -19,15 +19,6 @@ package params
 import "math/big"
 
 var (
-	TestNetHomesteadBlock = big.NewInt(494000)    // testnet homestead block
-	MainNetHomesteadBlock = big.NewInt(1150000)   // mainnet homestead block
-	HomesteadBlock        = MainNetHomesteadBlock // homestead block used to check against
+	TestNetHomesteadBlock = big.NewInt(494000)  // testnet homestead block
+	MainNetHomesteadBlock = big.NewInt(1150000) // mainnet homestead block
 )
-
-func IsHomestead(blockNumber *big.Int) bool {
-	// for unit tests TODO: flip to true after homestead is live
-	if blockNumber == nil {
-		return false
-	}
-	return blockNumber.Cmp(HomesteadBlock) >= 0
-}
diff --git a/tests/block_test.go b/tests/block_test.go
index 71dcc461538fd67a9594546cec2d8835ead87004..c258268dbbcc21d1aef123c544fd90118756ad11 100644
--- a/tests/block_test.go
+++ b/tests/block_test.go
@@ -20,77 +20,66 @@ import (
 	"math/big"
 	"path/filepath"
 	"testing"
-
-	"github.com/ethereum/go-ethereum/params"
 )
 
 func TestBcValidBlockTests(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
-	err := RunBlockTest(filepath.Join(blockTestDir, "bcValidBlockTest.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcValidBlockTest.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestBcUncleHeaderValidityTests(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
-	err := RunBlockTest(filepath.Join(blockTestDir, "bcUncleHeaderValiditiy.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcUncleHeaderValiditiy.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestBcUncleTests(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
-	err := RunBlockTest(filepath.Join(blockTestDir, "bcUncleTest.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcUncleTest.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestBcForkUncleTests(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
-	err := RunBlockTest(filepath.Join(blockTestDir, "bcForkUncle.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcForkUncle.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestBcInvalidHeaderTests(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
-	err := RunBlockTest(filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestBcInvalidRLPTests(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
-	err := RunBlockTest(filepath.Join(blockTestDir, "bcInvalidRLPTest.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcInvalidRLPTest.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestBcRPCAPITests(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
-	err := RunBlockTest(filepath.Join(blockTestDir, "bcRPC_API_Test.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcRPC_API_Test.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestBcForkBlockTests(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
-	err := RunBlockTest(filepath.Join(blockTestDir, "bcForkBlockTest.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcForkBlockTest.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestBcForkStress(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
-	err := RunBlockTest(filepath.Join(blockTestDir, "bcForkStressTest.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcForkStressTest.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -100,24 +89,21 @@ func TestBcTotalDifficulty(t *testing.T) {
 	// skip because these will fail due to selfish mining fix
 	t.Skip()
 
-	params.HomesteadBlock = big.NewInt(1000000)
-	err := RunBlockTest(filepath.Join(blockTestDir, "bcTotalDifficultyTest.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcTotalDifficultyTest.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestBcWallet(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
-	err := RunBlockTest(filepath.Join(blockTestDir, "bcWalletTest.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcWalletTest.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestBcGasPricer(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
-	err := RunBlockTest(filepath.Join(blockTestDir, "bcGasPricerTest.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcGasPricerTest.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -125,8 +111,7 @@ func TestBcGasPricer(t *testing.T) {
 
 // TODO: iterate over files once we got more than a few
 func TestBcRandom(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
-	err := RunBlockTest(filepath.Join(blockTestDir, "RandomTests/bl201507071825GO.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "RandomTests/bl201507071825GO.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -136,16 +121,14 @@ func TestBcMultiChain(t *testing.T) {
 	// skip due to selfish mining
 	t.Skip()
 
-	params.HomesteadBlock = big.NewInt(1000000)
-	err := RunBlockTest(filepath.Join(blockTestDir, "bcMultiChainTest.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcMultiChainTest.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestBcState(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
-	err := RunBlockTest(filepath.Join(blockTestDir, "bcStateTest.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(1000000), filepath.Join(blockTestDir, "bcStateTest.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -153,88 +136,77 @@ func TestBcState(t *testing.T) {
 
 // Homestead tests
 func TestHomesteadBcValidBlockTests(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
-	err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcValidBlockTest.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcValidBlockTest.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestHomesteadBcUncleHeaderValidityTests(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
-	err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcUncleHeaderValiditiy.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcUncleHeaderValiditiy.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestHomesteadBcUncleTests(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
-	err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcUncleTest.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcUncleTest.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestHomesteadBcInvalidHeaderTests(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
-	err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcInvalidHeaderTest.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcInvalidHeaderTest.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestHomesteadBcRPCAPITests(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
-	err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcRPC_API_Test.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcRPC_API_Test.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestHomesteadBcForkStress(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
-	err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcForkStressTest.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcForkStressTest.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestHomesteadBcTotalDifficulty(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
-	err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcTotalDifficultyTest.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcTotalDifficultyTest.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestHomesteadBcWallet(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
-	err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcWalletTest.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcWalletTest.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestHomesteadBcGasPricer(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
-	err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcGasPricerTest.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcGasPricerTest.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestHomesteadBcMultiChain(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
-	err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcMultiChainTest.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcMultiChainTest.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestHomesteadBcState(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
-	err := RunBlockTest(filepath.Join(blockTestDir, "Homestead", "bcStateTest.json"), BlockSkipTests)
+	err := RunBlockTest(big.NewInt(0), filepath.Join(blockTestDir, "Homestead", "bcStateTest.json"), BlockSkipTests)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/tests/block_test_util.go b/tests/block_test_util.go
index f517eddd1dc47577a761c7510627ae59d33e4eea..482a9ae0a0270cb6077ec30985e0ec7646f758a3 100644
--- a/tests/block_test_util.go
+++ b/tests/block_test_util.go
@@ -108,7 +108,7 @@ type btTransaction struct {
 	Value    string
 }
 
-func RunBlockTestWithReader(r io.Reader, skipTests []string) error {
+func RunBlockTestWithReader(homesteadBlock *big.Int, r io.Reader, skipTests []string) error {
 	btjs := make(map[string]*btJSON)
 	if err := readJson(r, &btjs); err != nil {
 		return err
@@ -119,13 +119,13 @@ func RunBlockTestWithReader(r io.Reader, skipTests []string) error {
 		return err
 	}
 
-	if err := runBlockTests(bt, skipTests); err != nil {
+	if err := runBlockTests(homesteadBlock, bt, skipTests); err != nil {
 		return err
 	}
 	return nil
 }
 
-func RunBlockTest(file string, skipTests []string) error {
+func RunBlockTest(homesteadBlock *big.Int, file string, skipTests []string) error {
 	btjs := make(map[string]*btJSON)
 	if err := readJsonFile(file, &btjs); err != nil {
 		return err
@@ -135,13 +135,13 @@ func RunBlockTest(file string, skipTests []string) error {
 	if err != nil {
 		return err
 	}
-	if err := runBlockTests(bt, skipTests); err != nil {
+	if err := runBlockTests(homesteadBlock, bt, skipTests); err != nil {
 		return err
 	}
 	return nil
 }
 
-func runBlockTests(bt map[string]*BlockTest, skipTests []string) error {
+func runBlockTests(homesteadBlock *big.Int, bt map[string]*BlockTest, skipTests []string) error {
 	skipTest := make(map[string]bool, len(skipTests))
 	for _, name := range skipTests {
 		skipTest[name] = true
@@ -153,7 +153,7 @@ func runBlockTests(bt map[string]*BlockTest, skipTests []string) error {
 			continue
 		}
 		// test the block
-		if err := runBlockTest(test); err != nil {
+		if err := runBlockTest(homesteadBlock, test); err != nil {
 			return fmt.Errorf("%s: %v", name, err)
 		}
 		glog.Infoln("Block test passed: ", name)
@@ -162,7 +162,7 @@ func runBlockTests(bt map[string]*BlockTest, skipTests []string) error {
 	return nil
 
 }
-func runBlockTest(test *BlockTest) error {
+func runBlockTest(homesteadBlock *big.Int, test *BlockTest) error {
 	ks := crypto.NewKeyStorePassphrase(filepath.Join(common.DefaultDataDir(), "keystore"), crypto.StandardScryptN, crypto.StandardScryptP)
 	am := accounts.NewManager(ks)
 	db, _ := ethdb.NewMemDatabase()
@@ -174,6 +174,7 @@ func runBlockTest(test *BlockTest) error {
 	}
 
 	cfg := &eth.Config{
+		ChainConfig:      &core.ChainConfig{HomesteadBlock: homesteadBlock},
 		TestGenesisState: db,
 		TestGenesisBlock: test.Genesis,
 		Etherbase:        common.Address{},
diff --git a/tests/state_test.go b/tests/state_test.go
index 4c1820944acd9531b58d89f0d87e0a725e62eadf..59646fd7ef10ca71b737d32df9d357f8d7640380 100644
--- a/tests/state_test.go
+++ b/tests/state_test.go
@@ -21,18 +21,8 @@ import (
 	"os"
 	"path/filepath"
 	"testing"
-
-	"github.com/ethereum/go-ethereum/core/vm"
-	"github.com/ethereum/go-ethereum/params"
 )
 
-func init() {
-	if os.Getenv("JITVM") == "true" {
-		vm.ForceJit = true
-		vm.EnableJit = true
-	}
-}
-
 func BenchmarkStateCall1024(b *testing.B) {
 	fn := filepath.Join(stateTestDir, "stCallCreateCallCodeTest.json")
 	if err := BenchVmTest(fn, bconf{"Call1024BalanceTooLow", true, os.Getenv("JITVM") == "true"}, b); err != nil {
@@ -41,188 +31,228 @@ func BenchmarkStateCall1024(b *testing.B) {
 }
 
 func TestStateSystemOperations(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
+	ruleSet := RuleSet{
+		HomesteadBlock: big.NewInt(1000000),
+	}
 
 	fn := filepath.Join(stateTestDir, "stSystemOperationsTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestStateExample(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
+	ruleSet := RuleSet{
+		HomesteadBlock: big.NewInt(1000000),
+	}
 
 	fn := filepath.Join(stateTestDir, "stExample.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestStatePreCompiledContracts(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
+	ruleSet := RuleSet{
+		HomesteadBlock: big.NewInt(1000000),
+	}
 
 	fn := filepath.Join(stateTestDir, "stPreCompiledContracts.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestStateRecursiveCreate(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
+	ruleSet := RuleSet{
+		HomesteadBlock: big.NewInt(1000000),
+	}
 
 	fn := filepath.Join(stateTestDir, "stRecursiveCreate.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestStateSpecial(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
+	ruleSet := RuleSet{
+		HomesteadBlock: big.NewInt(1000000),
+	}
 
 	fn := filepath.Join(stateTestDir, "stSpecialTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestStateRefund(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
+	ruleSet := RuleSet{
+		HomesteadBlock: big.NewInt(1000000),
+	}
 
 	fn := filepath.Join(stateTestDir, "stRefundTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestStateBlockHash(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
+	ruleSet := RuleSet{
+		HomesteadBlock: big.NewInt(1000000),
+	}
 
 	fn := filepath.Join(stateTestDir, "stBlockHashTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestStateInitCode(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
+	ruleSet := RuleSet{
+		HomesteadBlock: big.NewInt(1000000),
+	}
 
 	fn := filepath.Join(stateTestDir, "stInitCodeTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestStateLog(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
+	ruleSet := RuleSet{
+		HomesteadBlock: big.NewInt(1000000),
+	}
 
 	fn := filepath.Join(stateTestDir, "stLogTests.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestStateTransaction(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
+	ruleSet := RuleSet{
+		HomesteadBlock: big.NewInt(1000000),
+	}
 
 	fn := filepath.Join(stateTestDir, "stTransactionTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestStateTransition(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
+	ruleSet := RuleSet{
+		HomesteadBlock: big.NewInt(1000000),
+	}
 
 	fn := filepath.Join(stateTestDir, "stTransitionTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestCallCreateCallCode(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
+	ruleSet := RuleSet{
+		HomesteadBlock: big.NewInt(1000000),
+	}
 
 	fn := filepath.Join(stateTestDir, "stCallCreateCallCodeTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestCallCodes(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
+	ruleSet := RuleSet{
+		HomesteadBlock: big.NewInt(1000000),
+	}
 
 	fn := filepath.Join(stateTestDir, "stCallCodes.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestDelegateCall(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
+	ruleSet := RuleSet{
+		HomesteadBlock: big.NewInt(1000000),
+	}
 
 	fn := filepath.Join(stateTestDir, "stDelegatecallTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestMemory(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
+	ruleSet := RuleSet{
+		HomesteadBlock: big.NewInt(1000000),
+	}
 
 	fn := filepath.Join(stateTestDir, "stMemoryTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestMemoryStress(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
+	ruleSet := RuleSet{
+		HomesteadBlock: big.NewInt(1000000),
+	}
 
 	if os.Getenv("TEST_VM_COMPLEX") == "" {
 		t.Skip()
 	}
 	fn := filepath.Join(stateTestDir, "stMemoryStressTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestQuadraticComplexity(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
+	ruleSet := RuleSet{
+		HomesteadBlock: big.NewInt(1000000),
+	}
 
 	if os.Getenv("TEST_VM_COMPLEX") == "" {
 		t.Skip()
 	}
 	fn := filepath.Join(stateTestDir, "stQuadraticComplexityTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestSolidity(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
+	ruleSet := RuleSet{
+		HomesteadBlock: big.NewInt(1000000),
+	}
 
 	fn := filepath.Join(stateTestDir, "stSolidityTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestWallet(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
+	ruleSet := RuleSet{
+		HomesteadBlock: big.NewInt(1000000),
+	}
 
 	fn := filepath.Join(stateTestDir, "stWalletTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestStateTestsRandom(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(1000000)
+	ruleSet := RuleSet{
+		HomesteadBlock: big.NewInt(1000000),
+	}
 
 	fns, _ := filepath.Glob("./files/StateTests/RandomTests/*")
 	for _, fn := range fns {
-		if err := RunStateTest(fn, StateSkipTests); err != nil {
+		if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 			t.Error(err)
 		}
 	}
@@ -230,151 +260,172 @@ func TestStateTestsRandom(t *testing.T) {
 
 // homestead tests
 func TestHomesteadStateSystemOperations(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
+	ruleSet := RuleSet{
+		HomesteadBlock: new(big.Int),
+	}
 
 	fn := filepath.Join(stateTestDir, "Homestead", "stSystemOperationsTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestHomesteadStatePreCompiledContracts(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
+	ruleSet := RuleSet{
+		HomesteadBlock: new(big.Int),
+	}
 
 	fn := filepath.Join(stateTestDir, "Homestead", "stPreCompiledContracts.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestHomesteadStateRecursiveCreate(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
-
-	fn := filepath.Join(stateTestDir, "Homestead", "stRecursiveCreate.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
-		t.Error(err)
+	ruleSet := RuleSet{
+		HomesteadBlock: new(big.Int),
 	}
-}
-
-func TestHomesteadStateSpecial(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
 
 	fn := filepath.Join(stateTestDir, "Homestead", "stSpecialTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestHomesteadStateRefund(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
+	ruleSet := RuleSet{
+		HomesteadBlock: new(big.Int),
+	}
 
 	fn := filepath.Join(stateTestDir, "Homestead", "stRefundTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestHomesteadStateInitCode(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
+	ruleSet := RuleSet{
+		HomesteadBlock: new(big.Int),
+	}
 
 	fn := filepath.Join(stateTestDir, "Homestead", "stInitCodeTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestHomesteadStateLog(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
+	ruleSet := RuleSet{
+		HomesteadBlock: new(big.Int),
+	}
 
 	fn := filepath.Join(stateTestDir, "Homestead", "stLogTests.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestHomesteadStateTransaction(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
+	ruleSet := RuleSet{
+		HomesteadBlock: new(big.Int),
+	}
 
 	fn := filepath.Join(stateTestDir, "Homestead", "stTransactionTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestHomesteadCallCreateCallCode(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
+	ruleSet := RuleSet{
+		HomesteadBlock: new(big.Int),
+	}
 
 	fn := filepath.Join(stateTestDir, "Homestead", "stCallCreateCallCodeTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestHomesteadCallCodes(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
+	ruleSet := RuleSet{
+		HomesteadBlock: new(big.Int),
+	}
 
 	fn := filepath.Join(stateTestDir, "Homestead", "stCallCodes.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestHomesteadMemory(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
+	ruleSet := RuleSet{
+		HomesteadBlock: new(big.Int),
+	}
 
 	fn := filepath.Join(stateTestDir, "Homestead", "stMemoryTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestHomesteadMemoryStress(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
+	ruleSet := RuleSet{
+		HomesteadBlock: new(big.Int),
+	}
 
 	if os.Getenv("TEST_VM_COMPLEX") == "" {
 		t.Skip()
 	}
 	fn := filepath.Join(stateTestDir, "Homestead", "stMemoryStressTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestHomesteadQuadraticComplexity(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
+	ruleSet := RuleSet{
+		HomesteadBlock: new(big.Int),
+	}
 
 	if os.Getenv("TEST_VM_COMPLEX") == "" {
 		t.Skip()
 	}
 	fn := filepath.Join(stateTestDir, "Homestead", "stQuadraticComplexityTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestHomesteadWallet(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
+	ruleSet := RuleSet{
+		HomesteadBlock: new(big.Int),
+	}
 
 	fn := filepath.Join(stateTestDir, "Homestead", "stWalletTest.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestHomesteadDelegateCodes(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
+	ruleSet := RuleSet{
+		HomesteadBlock: new(big.Int),
+	}
 
 	fn := filepath.Join(stateTestDir, "Homestead", "stCallDelegateCodes.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
 
 func TestHomesteadDelegateCodesCallCode(t *testing.T) {
-	params.HomesteadBlock = big.NewInt(0)
+	ruleSet := RuleSet{
+		HomesteadBlock: new(big.Int),
+	}
 
 	fn := filepath.Join(stateTestDir, "Homestead", "stCallDelegateCodesCallCode.json")
-	if err := RunStateTest(fn, StateSkipTests); err != nil {
+	if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
 		t.Error(err)
 	}
 }
diff --git a/tests/state_test_util.go b/tests/state_test_util.go
index 50be3a1ac8e98526ba78eb219a28ae428b7a61e2..9d6069ac70067738cba37cb7ad5793b2753569a2 100644
--- a/tests/state_test_util.go
+++ b/tests/state_test_util.go
@@ -34,26 +34,26 @@ import (
 	"github.com/ethereum/go-ethereum/logger/glog"
 )
 
-func RunStateTestWithReader(r io.Reader, skipTests []string) error {
+func RunStateTestWithReader(ruleSet RuleSet, r io.Reader, skipTests []string) error {
 	tests := make(map[string]VmTest)
 	if err := readJson(r, &tests); err != nil {
 		return err
 	}
 
-	if err := runStateTests(tests, skipTests); err != nil {
+	if err := runStateTests(ruleSet, tests, skipTests); err != nil {
 		return err
 	}
 
 	return nil
 }
 
-func RunStateTest(p string, skipTests []string) error {
+func RunStateTest(ruleSet RuleSet, p string, skipTests []string) error {
 	tests := make(map[string]VmTest)
 	if err := readJsonFile(p, &tests); err != nil {
 		return err
 	}
 
-	if err := runStateTests(tests, skipTests); err != nil {
+	if err := runStateTests(ruleSet, tests, skipTests); err != nil {
 		return err
 	}
 
@@ -61,7 +61,7 @@ func RunStateTest(p string, skipTests []string) error {
 
 }
 
-func BenchStateTest(p string, conf bconf, b *testing.B) error {
+func BenchStateTest(ruleSet RuleSet, p string, conf bconf, b *testing.B) error {
 	tests := make(map[string]VmTest)
 	if err := readJsonFile(p, &tests); err != nil {
 		return err
@@ -71,11 +71,6 @@ func BenchStateTest(p string, conf bconf, b *testing.B) error {
 		return fmt.Errorf("test not found: %s", conf.name)
 	}
 
-	pJit := vm.EnableJit
-	vm.EnableJit = conf.jit
-	pForceJit := vm.ForceJit
-	vm.ForceJit = conf.precomp
-
 	// XXX Yeah, yeah...
 	env := make(map[string]string)
 	env["currentCoinbase"] = test.Env.CurrentCoinbase
@@ -91,16 +86,13 @@ func BenchStateTest(p string, conf bconf, b *testing.B) error {
 
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		benchStateTest(test, env, b)
+		benchStateTest(ruleSet, test, env, b)
 	}
 
-	vm.EnableJit = pJit
-	vm.ForceJit = pForceJit
-
 	return nil
 }
 
-func benchStateTest(test VmTest, env map[string]string, b *testing.B) {
+func benchStateTest(ruleSet RuleSet, test VmTest, env map[string]string, b *testing.B) {
 	b.StopTimer()
 	db, _ := ethdb.NewMemDatabase()
 	statedb, _ := state.New(common.Hash{}, db)
@@ -113,10 +105,10 @@ func benchStateTest(test VmTest, env map[string]string, b *testing.B) {
 	}
 	b.StartTimer()
 
-	RunState(statedb, env, test.Exec)
+	RunState(ruleSet, statedb, env, test.Exec)
 }
 
-func runStateTests(tests map[string]VmTest, skipTests []string) error {
+func runStateTests(ruleSet RuleSet, tests map[string]VmTest, skipTests []string) error {
 	skipTest := make(map[string]bool, len(skipTests))
 	for _, name := range skipTests {
 		skipTest[name] = true
@@ -129,7 +121,7 @@ func runStateTests(tests map[string]VmTest, skipTests []string) error {
 		}
 
 		//fmt.Println("StateTest:", name)
-		if err := runStateTest(test); err != nil {
+		if err := runStateTest(ruleSet, test); err != nil {
 			return fmt.Errorf("%s: %s\n", name, err.Error())
 		}
 
@@ -140,7 +132,7 @@ func runStateTests(tests map[string]VmTest, skipTests []string) error {
 
 }
 
-func runStateTest(test VmTest) error {
+func runStateTest(ruleSet RuleSet, test VmTest) error {
 	db, _ := ethdb.NewMemDatabase()
 	statedb, _ := state.New(common.Hash{}, db)
 	for addr, account := range test.Pre {
@@ -171,7 +163,7 @@ func runStateTest(test VmTest) error {
 		logs vm.Logs
 	)
 
-	ret, logs, _, _ = RunState(statedb, env, test.Transaction)
+	ret, logs, _, _ = RunState(ruleSet, statedb, env, test.Transaction)
 
 	// Compare expected and actual return
 	rexp := common.FromHex(test.Out)
@@ -219,7 +211,7 @@ func runStateTest(test VmTest) error {
 	return nil
 }
 
-func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, vm.Logs, *big.Int, error) {
+func RunState(ruleSet RuleSet, statedb *state.StateDB, env, tx map[string]string) ([]byte, vm.Logs, *big.Int, error) {
 	var (
 		data  = common.FromHex(tx["data"])
 		gas   = common.Big(tx["gasLimit"])
@@ -241,7 +233,7 @@ func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, vm.Log
 	key, _ := hex.DecodeString(tx["secretKey"])
 	addr := crypto.PubkeyToAddress(crypto.ToECDSA(key).PublicKey)
 	message := NewMessage(addr, to, data, value, gas, price, nonce)
-	vmenv := NewEnvFromMap(statedb, env, tx)
+	vmenv := NewEnvFromMap(ruleSet, statedb, env, tx)
 	vmenv.origin = addr
 	ret, _, err := core.ApplyMessage(vmenv, message, gaspool)
 	if core.IsNonceErr(err) || core.IsInvalidTxErr(err) || core.IsGasLimitErr(err) {
diff --git a/tests/transaction_test_util.go b/tests/transaction_test_util.go
index 6302b9d5b725d0e15eb302917fc2d3f9783369f3..178f90284df83488bd942f884435f5623a362917 100644
--- a/tests/transaction_test_util.go
+++ b/tests/transaction_test_util.go
@@ -21,10 +21,10 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"math/big"
 	"runtime"
 
 	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/core"
 	"github.com/ethereum/go-ethereum/core/types"
 	"github.com/ethereum/go-ethereum/logger/glog"
 	"github.com/ethereum/go-ethereum/params"
@@ -91,8 +91,6 @@ func RunTransactionTests(file string, skipTests []string) error {
 }
 
 func runTransactionTests(tests map[string]TransactionTest, skipTests []string) error {
-	params.HomesteadBlock = big.NewInt(900000)
-
 	skipTest := make(map[string]bool, len(skipTests))
 	for _, name := range skipTests {
 		skipTest[name] = true
@@ -166,7 +164,8 @@ func verifyTxFields(txTest TransactionTest, decodedTx *types.Transaction) (err e
 		decodedSender common.Address
 	)
 
-	if params.IsHomestead(common.String2Big(txTest.Blocknumber)) {
+	chainConfig := &core.ChainConfig{HomesteadBlock: params.MainNetHomesteadBlock}
+	if chainConfig.IsHomestead(common.String2Big(txTest.Blocknumber)) {
 		decodedSender, err = decodedTx.From()
 	} else {
 		decodedSender, err = decodedTx.FromFrontier()
diff --git a/tests/util.go b/tests/util.go
index a0eb8158e0875fc6ecf0719ddab94ba844632bd1..9cb43ccb18fcbce3be85185d1cb61ac417869fae 100644
--- a/tests/util.go
+++ b/tests/util.go
@@ -20,6 +20,7 @@ import (
 	"bytes"
 	"fmt"
 	"math/big"
+	"os"
 
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/core"
@@ -31,8 +32,17 @@ import (
 	"github.com/ethereum/go-ethereum/logger/glog"
 )
 
+var (
+	ForceJit  bool
+	EnableJit bool
+)
+
 func init() {
 	glog.SetV(0)
+	if os.Getenv("JITVM") == "true" {
+		ForceJit = true
+		EnableJit = true
+	}
 }
 
 func checkLogs(tlog []Log, logs vm.Logs) error {
@@ -129,7 +139,16 @@ type VmTest struct {
 	PostStateRoot string
 }
 
+type RuleSet struct {
+	HomesteadBlock *big.Int
+}
+
+func (r RuleSet) IsHomestead(n *big.Int) bool {
+	return n.Cmp(r.HomesteadBlock) >= 0
+}
+
 type Env struct {
+	ruleSet      RuleSet
 	depth        int
 	state        *state.StateDB
 	skipTransfer bool
@@ -152,9 +171,10 @@ type Env struct {
 	evm *vm.EVM
 }
 
-func NewEnv(state *state.StateDB) *Env {
+func NewEnv(ruleSet RuleSet, state *state.StateDB) *Env {
 	env := &Env{
-		state: state,
+		ruleSet: ruleSet,
+		state:   state,
 	}
 	return env
 }
@@ -167,8 +187,8 @@ func (self *Env) AddStructLog(log vm.StructLog) {
 	self.logs = append(self.logs, log)
 }
 
-func NewEnvFromMap(state *state.StateDB, envValues map[string]string, exeValues map[string]string) *Env {
-	env := NewEnv(state)
+func NewEnvFromMap(ruleSet RuleSet, state *state.StateDB, envValues map[string]string, exeValues map[string]string) *Env {
+	env := NewEnv(ruleSet, state)
 
 	env.origin = common.HexToAddress(exeValues["caller"])
 	env.parent = common.HexToHash(envValues["previousHash"])
@@ -179,11 +199,15 @@ func NewEnvFromMap(state *state.StateDB, envValues map[string]string, exeValues
 	env.gasLimit = common.Big(envValues["currentGasLimit"])
 	env.Gas = new(big.Int)
 
-	env.evm = vm.New(env, nil)
+	env.evm = vm.New(env, vm.Config{
+		EnableJit: EnableJit,
+		ForceJit:  ForceJit,
+	})
 
 	return env
 }
 
+func (self *Env) RuleSet() vm.RuleSet      { return self.ruleSet }
 func (self *Env) Vm() vm.Vm                { return self.evm }
 func (self *Env) Origin() common.Address   { return self.origin }
 func (self *Env) BlockNumber() *big.Int    { return self.number }
diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go
index ddd14b1a3e4dcf47838ccf516ddfe03117cd849c..d17c59905cba1934e649a44c9d99dfc5394942b2 100644
--- a/tests/vm_test_util.go
+++ b/tests/vm_test_util.go
@@ -29,6 +29,7 @@ import (
 	"github.com/ethereum/go-ethereum/core/vm"
 	"github.com/ethereum/go-ethereum/ethdb"
 	"github.com/ethereum/go-ethereum/logger/glog"
+	"github.com/ethereum/go-ethereum/params"
 )
 
 func RunVmTestWithReader(r io.Reader, skipTests []string) error {
@@ -67,11 +68,6 @@ func BenchVmTest(p string, conf bconf, b *testing.B) error {
 		return fmt.Errorf("test not found: %s", conf.name)
 	}
 
-	pJit := vm.EnableJit
-	vm.EnableJit = conf.jit
-	pForceJit := vm.ForceJit
-	vm.ForceJit = conf.precomp
-
 	env := make(map[string]string)
 	env["currentCoinbase"] = test.Env.CurrentCoinbase
 	env["currentDifficulty"] = test.Env.CurrentDifficulty
@@ -99,9 +95,6 @@ func BenchVmTest(p string, conf bconf, b *testing.B) error {
 		benchVmTest(test, env, b)
 	}
 
-	vm.EnableJit = pJit
-	vm.ForceJit = pForceJit
-
 	return nil
 }
 
@@ -248,7 +241,7 @@ func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, vm.Logs,
 
 	caller := state.GetOrNewStateObject(from)
 
-	vmenv := NewEnvFromMap(state, env, exec)
+	vmenv := NewEnvFromMap(RuleSet{params.MainNetHomesteadBlock}, state, env, exec)
 	vmenv.vmTest = true
 	vmenv.skipTransfer = true
 	vmenv.initial = true