diff --git a/cmd/geth/blocktestcmd.go b/cmd/geth/blocktestcmd.go
index 116eec2b37c89c6d41401160db9f72c7a638c3ab..ffea4400ee5756ff81c959d2be78d577d7518a7f 100644
--- a/cmd/geth/blocktestcmd.go
+++ b/cmd/geth/blocktestcmd.go
@@ -86,7 +86,6 @@ func runBlockTest(ctx *cli.Context) {
 }
 
 func runOneBlockTest(ctx *cli.Context, test *tests.BlockTest) (*eth.Ethereum, error) {
-	// TODO remove in favor of logic contained in tests package
 	cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
 	cfg.NewDB = func(path string) (common.Database, error) { return ethdb.NewMemDatabase() }
 	cfg.MaxPeers = 0 // disable network
diff --git a/cmd/geth/contracts.go b/cmd/geth/contracts.go
deleted file mode 100644
index 1f27838d15f7ac6fe8edc06758e8e7cd13ed2c6d..0000000000000000000000000000000000000000
--- a/cmd/geth/contracts.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package main
-
-var (
-	globalRegistrar     = `var GlobalRegistrar = web3.eth.contract([{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"name","outputs":[{"name":"o_name","type":"bytes32"}],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"content","outputs":[{"name":"","type":"bytes32"}],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"addr","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserve","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"subRegistrar","outputs":[{"name":"o_subRegistrar","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_newOwner","type":"address"}],"name":"transfer","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_registrar","type":"address"}],"name":"setSubRegistrar","outputs":[],"type":"function"},{"constant":false,"inputs":[],"name":"Registrar","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_a","type":"address"},{"name":"_primary","type":"bool"}],"name":"setAddress","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_content","type":"bytes32"}],"name":"setContent","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"disown","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"register","outputs":[{"name":"","type":"address"}],"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"}],"name":"Changed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"addr","type":"address"}],"name":"PrimaryChanged","type":"event"}]);`
-	globalRegistrarAddr = "0xc6d9d2cd449a754c494264e1809c50e34d64562b"
-)
diff --git a/cmd/geth/js.go b/cmd/geth/js.go
index 01840ebd9bbd9c26610f2e1ef540fbb422bf04e4..06c92391302dd57e21b45d341f234cad985cfd8c 100644
--- a/cmd/geth/js.go
+++ b/cmd/geth/js.go
@@ -32,16 +32,17 @@ import (
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/common/docserver"
 	"github.com/ethereum/go-ethereum/common/natspec"
+	"github.com/ethereum/go-ethereum/common/registrar"
 	"github.com/ethereum/go-ethereum/eth"
 	re "github.com/ethereum/go-ethereum/jsre"
 	"github.com/ethereum/go-ethereum/rpc"
 	"github.com/ethereum/go-ethereum/rpc/api"
 	"github.com/ethereum/go-ethereum/rpc/codec"
 	"github.com/ethereum/go-ethereum/rpc/comms"
+	"github.com/ethereum/go-ethereum/rpc/shared"
 	"github.com/ethereum/go-ethereum/xeth"
 	"github.com/peterh/liner"
 	"github.com/robertkrimen/otto"
-	"github.com/ethereum/go-ethereum/rpc/shared"
 )
 
 type prompter interface {
@@ -69,6 +70,7 @@ func (r dumbterm) PasswordPrompt(p string) (string, error) {
 func (r dumbterm) AppendHistory(string) {}
 
 type jsre struct {
+	ds         *docserver.DocServer
 	re         *re.JSRE
 	ethereum   *eth.Ethereum
 	xeth       *xeth.XEth
@@ -143,6 +145,7 @@ func newLightweightJSRE(libPath string, client comms.EthereumClient, interactive
 	js := &jsre{ps1: "> "}
 	js.wait = make(chan *big.Int)
 	js.client = client
+	js.ds = docserver.New("/")
 
 	if f == nil {
 		f = js
@@ -180,6 +183,7 @@ func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain string, client comms.Et
 	if f == nil {
 		f = js
 	}
+	js.ds = docserver.New("/")
 	js.xeth = xeth.New(ethereum, f)
 	js.wait = js.xeth.UpdateState()
 	js.client = client
@@ -331,15 +335,13 @@ func (js *jsre) apiBindings(f xeth.Frontend) error {
 		utils.Fatalf("Error setting namespaces: %v", err)
 	}
 
-	js.re.Eval(globalRegistrar + "registrar = GlobalRegistrar.at(\"" + globalRegistrarAddr + "\");")
+	js.re.Eval(`var GlobalRegistrar = eth.contract(` + registrar.GlobalRegistrarAbi + `);	 registrar = GlobalRegistrar.at("` + registrar.GlobalRegistrarAddr + `");`)
 	return nil
 }
 
-var ds, _ = docserver.New("/")
-
 func (self *jsre) ConfirmTransaction(tx string) bool {
 	if self.ethereum.NatSpec {
-		notice := natspec.GetNotice(self.xeth, tx, ds)
+		notice := natspec.GetNotice(self.xeth, tx, self.ds)
 		fmt.Println(notice)
 		answer, _ := self.Prompt("Confirm Transaction [y/n]")
 		return strings.HasPrefix(strings.Trim(answer, " "), "y")
diff --git a/cmd/geth/js_test.go b/cmd/geth/js_test.go
index 480f77c9175df0adcc0255c8bce10bb56b2f9bc4..646ca404ad02d00eca40afdab80f0d59fc39dd85 100644
--- a/cmd/geth/js_test.go
+++ b/cmd/geth/js_test.go
@@ -3,21 +3,22 @@ package main
 import (
 	"fmt"
 	"io/ioutil"
+	"math/big"
 	"os"
 	"path/filepath"
 	"regexp"
 	"runtime"
 	"strconv"
 	"testing"
+	"time"
 
 	"github.com/ethereum/go-ethereum/accounts"
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/common/compiler"
 	"github.com/ethereum/go-ethereum/common/docserver"
 	"github.com/ethereum/go-ethereum/common/natspec"
-	"github.com/ethereum/go-ethereum/common/resolver"
+	"github.com/ethereum/go-ethereum/common/registrar"
 	"github.com/ethereum/go-ethereum/core"
-	"github.com/ethereum/go-ethereum/core/state"
 	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/eth"
 	"github.com/ethereum/go-ethereum/rpc/codec"
@@ -43,7 +44,6 @@ var (
 
 type testjethre struct {
 	*jsre
-	stateDb     *state.StateDB
 	lastConfirm string
 	ds          *docserver.DocServer
 }
@@ -64,6 +64,10 @@ func (self *testjethre) ConfirmTransaction(tx string) bool {
 }
 
 func testJEthRE(t *testing.T) (string, *testjethre, *eth.Ethereum) {
+	return testREPL(t, nil)
+}
+
+func testREPL(t *testing.T, config func(*eth.Config)) (string, *testjethre, *eth.Ethereum) {
 	tmp, err := ioutil.TempDir("", "geth-test")
 	if err != nil {
 		t.Fatal(err)
@@ -74,14 +78,19 @@ func testJEthRE(t *testing.T) (string, *testjethre, *eth.Ethereum) {
 
 	ks := crypto.NewKeyStorePlain(filepath.Join(tmp, "keystore"))
 	am := accounts.NewManager(ks)
-	ethereum, err := eth.New(&eth.Config{
+	conf := &eth.Config{
 		NodeKey:        testNodeKey,
 		DataDir:        tmp,
 		AccountManager: am,
 		MaxPeers:       0,
 		Name:           "test",
 		SolcPath:       testSolcPath,
-	})
+		PowTest:        true,
+	}
+	if config != nil {
+		config(conf)
+	}
+	ethereum, err := eth.New(conf)
 	if err != nil {
 		t.Fatal("%v", err)
 	}
@@ -102,25 +111,16 @@ func testJEthRE(t *testing.T) (string, *testjethre, *eth.Ethereum) {
 	}
 
 	assetPath := filepath.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist", "assets", "ext")
-	ds, err := docserver.New("/")
-	if err != nil {
-		t.Errorf("Error creating DocServer: %v", err)
-	}
-	tf := &testjethre{ds: ds, stateDb: ethereum.ChainManager().State().Copy()}
 	client := comms.NewInProcClient(codec.JSON)
+	ds := docserver.New("/")
+	tf := &testjethre{ds: ds}
 	repl := newJSRE(ethereum, assetPath, "", client, false, tf)
 	tf.jsre = repl
 	return tmp, tf, ethereum
 }
 
-// this line below is needed for transaction to be applied to the state in testing
-// the heavy lifing is done in XEth.ApplyTestTxs
-// this is fragile, overwriting xeth will result in
-// process leaking since xeth loops cannot quit safely
-// should be replaced by proper mining with testDAG for easy full integration tests
-// txc, self.xeth = self.xeth.ApplyTestTxs(self.xeth.repl.stateDb, coinbase, txc)
-
 func TestNodeInfo(t *testing.T) {
+	t.Skip("broken after p2p update")
 	tmp, repl, ethereum := testJEthRE(t)
 	if err := ethereum.Start(); err != nil {
 		t.Fatalf("error starting ethereum: %v", err)
@@ -254,8 +254,12 @@ func TestSignature(t *testing.T) {
 }
 
 func TestContract(t *testing.T) {
-	t.Skip()
-	tmp, repl, ethereum := testJEthRE(t)
+	t.Skip("contract testing is implemented with mining in ethash test mode. This takes about 7seconds to run. Unskip and run on demand")
+	coinbase := common.HexToAddress(testAddress)
+	tmp, repl, ethereum := testREPL(t, func(conf *eth.Config) {
+		conf.Etherbase = testAddress
+		conf.PowTest = true
+	})
 	if err := ethereum.Start(); err != nil {
 		t.Errorf("error starting ethereum: %v", err)
 		return
@@ -263,12 +267,26 @@ func TestContract(t *testing.T) {
 	defer ethereum.Stop()
 	defer os.RemoveAll(tmp)
 
-	var txc uint64
-	coinbase := common.HexToAddress(testAddress)
-	resolver.New(repl.xeth).CreateContracts(coinbase)
-	// time.Sleep(1000 * time.Millisecond)
+	reg := registrar.New(repl.xeth)
+	_, err := reg.SetGlobalRegistrar("", coinbase)
+	if err != nil {
+		t.Errorf("error setting HashReg: %v", err)
+	}
+	_, err = reg.SetHashReg("", coinbase)
+	if err != nil {
+		t.Errorf("error setting HashReg: %v", err)
+	}
+	_, err = reg.SetUrlHint("", coinbase)
+	if err != nil {
+		t.Errorf("error setting HashReg: %v", err)
+	}
+	/* TODO:
+	* lookup receipt and contract addresses by tx hash
+	* name registration for HashReg and UrlHint addresses
+	* mine those transactions
+	* then set once more SetHashReg SetUrlHint
+	 */
 
-	// checkEvalJSON(t, repl, `eth.getBlock("pending", true).transactions.length`, `2`)
 	source := `contract test {\n` +
 		"   /// @notice Will multiply `a` by 7." + `\n` +
 		`   function multiply(uint a) returns(uint d) {\n` +
@@ -276,14 +294,20 @@ func TestContract(t *testing.T) {
 		`   }\n` +
 		`}\n`
 
-	checkEvalJSON(t, repl, `admin.contractInfo.stop()`, `true`)
+	if checkEvalJSON(t, repl, `admin.stopNatSpec()`, `true`) != nil {
+		return
+	}
 
 	contractInfo, err := ioutil.ReadFile("info_test.json")
 	if err != nil {
 		t.Fatalf("%v", err)
 	}
-	checkEvalJSON(t, repl, `primary = eth.accounts[0]`, `"`+testAddress+`"`)
-	checkEvalJSON(t, repl, `source = "`+source+`"`, `"`+source+`"`)
+	if checkEvalJSON(t, repl, `primary = eth.accounts[0]`, `"`+testAddress+`"`) != nil {
+		return
+	}
+	if checkEvalJSON(t, repl, `source = "`+source+`"`, `"`+source+`"`) != nil {
+		return
+	}
 
 	// if solc is found with right version, test it, otherwise read from file
 	sol, err := compiler.New("")
@@ -303,69 +327,160 @@ func TestContract(t *testing.T) {
 			t.Errorf("%v", err)
 		}
 	} else {
-		checkEvalJSON(t, repl, `contract = eth.compile.solidity(source).test`, string(contractInfo))
+		if checkEvalJSON(t, repl, `contract = eth.compile.solidity(source).test`, string(contractInfo)) != nil {
+			return
+		}
 	}
 
-	checkEvalJSON(t, repl, `contract.code`, `"0x605880600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b603d6004803590602001506047565b8060005260206000f35b60006007820290506053565b91905056"`)
+	if checkEvalJSON(t, repl, `contract.code`, `"0x605880600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b603d6004803590602001506047565b8060005260206000f35b60006007820290506053565b91905056"`) != nil {
+		return
+	}
 
-	checkEvalJSON(
+	if checkEvalJSON(
 		t, repl,
-		`contractaddress = eth.sendTransaction({from: primary, data: contract.code })`,
-		`"0x5dcaace5982778b409c524873b319667eba5d074"`,
-	)
+		`contractaddress = eth.sendTransaction({from: primary, data: contract.code})`,
+		`"0x46d69d55c3c4b86a924a92c9fc4720bb7bce1d74"`,
+	) != nil {
+		return
+	}
+
+	if !processTxs(repl, t, 8) {
+		return
+	}
 
 	callSetup := `abiDef = JSON.parse('[{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"type":"function"}]');
 Multiply7 = eth.contract(abiDef);
 multiply7 = Multiply7.at(contractaddress);
 `
-	// time.Sleep(1500 * time.Millisecond)
 	_, err = repl.re.Run(callSetup)
 	if err != nil {
 		t.Errorf("unexpected error setting up contract, got %v", err)
+		return
 	}
 
-	// checkEvalJSON(t, repl, `eth.getBlock("pending", true).transactions.length`, `3`)
-
-	// why is this sometimes failing?
-	// checkEvalJSON(t, repl, `multiply7.multiply.call(6)`, `42`)
 	expNotice := ""
 	if repl.lastConfirm != expNotice {
 		t.Errorf("incorrect confirmation message: expected %v, got %v", expNotice, repl.lastConfirm)
+		return
+	}
+
+	if checkEvalJSON(t, repl, `admin.startNatSpec()`, `true`) != nil {
+		return
+	}
+	if checkEvalJSON(t, repl, `multiply7.multiply.sendTransaction(6, { from: primary })`, `"0x4ef9088431a8033e4580d00e4eb2487275e031ff4163c7529df0ef45af17857b"`) != nil {
+		return
 	}
 
-	txc, repl.xeth = repl.xeth.ApplyTestTxs(repl.stateDb, coinbase, txc)
+	if !processTxs(repl, t, 1) {
+		return
+	}
 
-	checkEvalJSON(t, repl, `admin.contractInfo.start()`, `true`)
-	checkEvalJSON(t, repl, `multiply7.multiply.sendTransaction(6, { from: primary, gas: "1000000", gasPrice: "100000" })`, `undefined`)
-	expNotice = `About to submit transaction (no NatSpec info found for contract: content hash not found for '0x87e2802265838c7f14bb69eecd2112911af6767907a702eeaa445239fb20711b'): {"params":[{"to":"0x5dcaace5982778b409c524873b319667eba5d074","data": "0xc6888fa10000000000000000000000000000000000000000000000000000000000000006"}]}`
+	expNotice = `About to submit transaction (no NatSpec info found for contract: content hash not found for '0x87e2802265838c7f14bb69eecd2112911af6767907a702eeaa445239fb20711b'): {"params":[{"to":"0x46d69d55c3c4b86a924a92c9fc4720bb7bce1d74","data": "0xc6888fa10000000000000000000000000000000000000000000000000000000000000006"}]}`
 	if repl.lastConfirm != expNotice {
-		t.Errorf("incorrect confirmation message: expected %v, got %v", expNotice, repl.lastConfirm)
+		t.Errorf("incorrect confirmation message: expected\n%v, got\n%v", expNotice, repl.lastConfirm)
+		return
 	}
 
-	var contenthash = `"0x86d2b7cf1e72e9a7a3f8d96601f0151742a2f780f1526414304fbe413dc7f9bd"`
-	if sol != nil {
+	var contentHash = `"0x86d2b7cf1e72e9a7a3f8d96601f0151742a2f780f1526414304fbe413dc7f9bd"`
+	if sol != nil && solcVersion != sol.Version() {
 		modContractInfo := versionRE.ReplaceAll(contractInfo, []byte(`"compilerVersion":"`+sol.Version()+`"`))
-		_ = modContractInfo
-		// contenthash = crypto.Sha3(modContractInfo)
+		fmt.Printf("modified contractinfo:\n%s\n", modContractInfo)
+		contentHash = `"` + common.ToHex(crypto.Sha3([]byte(modContractInfo))) + `"`
 	}
-	checkEvalJSON(t, repl, `filename = "/tmp/info.json"`, `"/tmp/info.json"`)
-	checkEvalJSON(t, repl, `contenthash = admin.contractInfo.register(primary, contractaddress, contract, filename)`, contenthash)
-	checkEvalJSON(t, repl, `admin.contractInfo.registerUrl(primary, contenthash, "file://"+filename)`, `true`)
-	if err != nil {
-		t.Errorf("unexpected error registering, got %v", err)
+	if checkEvalJSON(t, repl, `filename = "/tmp/info.json"`, `"/tmp/info.json"`) != nil {
+		return
+	}
+	if checkEvalJSON(t, repl, `contentHash = admin.saveInfo(contract.info, filename)`, contentHash) != nil {
+		return
+	}
+	if checkEvalJSON(t, repl, `admin.register(primary, contractaddress, contentHash)`, `true`) != nil {
+		return
+	}
+	if checkEvalJSON(t, repl, `admin.registerUrl(primary, contentHash, "file://"+filename)`, `true`) != nil {
+		return
+	}
+
+	if checkEvalJSON(t, repl, `admin.startNatSpec()`, `true`) != nil {
+		return
 	}
 
-	checkEvalJSON(t, repl, `admin.contractInfo.start()`, `true`)
+	if !processTxs(repl, t, 3) {
+		return
+	}
 
-	// update state
-	txc, repl.xeth = repl.xeth.ApplyTestTxs(repl.stateDb, coinbase, txc)
+	if checkEvalJSON(t, repl, `multiply7.multiply.sendTransaction(6, { from: primary })`, `"0x66d7635c12ad0b231e66da2f987ca3dfdca58ffe49c6442aa55960858103fd0c"`) != nil {
+		return
+	}
+
+	if !processTxs(repl, t, 1) {
+		return
+	}
 
-	checkEvalJSON(t, repl, `multiply7.multiply.sendTransaction(6, { from: primary, gas: "1000000", gasPrice: "100000" })`, `undefined`)
 	expNotice = "Will multiply 6 by 7."
 	if repl.lastConfirm != expNotice {
-		t.Errorf("incorrect confirmation message: expected %v, got %v", expNotice, repl.lastConfirm)
+		t.Errorf("incorrect confirmation message: expected\n%v, got\n%v", expNotice, repl.lastConfirm)
+		return
 	}
+}
+
+func pendingTransactions(repl *testjethre, t *testing.T) (txc int64, err error) {
+	txs := repl.ethereum.TxPool().GetTransactions()
+	return int64(len(txs)), nil
+}
 
+func processTxs(repl *testjethre, t *testing.T, expTxc int) bool {
+	var txc int64
+	var err error
+	for i := 0; i < 50; i++ {
+		txc, err = pendingTransactions(repl, t)
+		if err != nil {
+			t.Errorf("unexpected error checking pending transactions: %v", err)
+			return false
+		}
+		if expTxc < int(txc) {
+			t.Errorf("too many pending transactions: expected %v, got %v", expTxc, txc)
+			return false
+		} else if expTxc == int(txc) {
+			break
+		}
+		time.Sleep(100 * time.Millisecond)
+	}
+	if int(txc) != expTxc {
+		t.Errorf("incorrect number of pending transactions, expected %v, got %v", expTxc, txc)
+		return false
+	}
+
+	err = repl.ethereum.StartMining(runtime.NumCPU())
+	if err != nil {
+		t.Errorf("unexpected error mining: %v", err)
+		return false
+	}
+	defer repl.ethereum.StopMining()
+
+	timer := time.NewTimer(100 * time.Second)
+	height := new(big.Int).Add(repl.xeth.CurrentBlock().Number(), big.NewInt(1))
+	repl.wait <- height
+	select {
+	case <-timer.C:
+		// if times out make sure the xeth loop does not block
+		go func() {
+			select {
+			case repl.wait <- nil:
+			case <-repl.wait:
+			}
+		}()
+	case <-repl.wait:
+	}
+	txc, err = pendingTransactions(repl, t)
+	if err != nil {
+		t.Errorf("unexpected error checking pending transactions: %v", err)
+		return false
+	}
+	if txc != 0 {
+		t.Errorf("%d trasactions were not mined", txc)
+		return false
+	}
+	return true
 }
 
 func checkEvalJSON(t *testing.T, re *testjethre, expr, want string) error {
diff --git a/common/compiler/solidity.go b/common/compiler/solidity.go
index caf86974e5f3b5654c03eb81ff927cb04a53e9b5..4d5ffb473e0f93ef4965c19cc60e0b46ff3e919f 100644
--- a/common/compiler/solidity.go
+++ b/common/compiler/solidity.go
@@ -185,12 +185,12 @@ func (sol *Solidity) Compile(source string) (contracts map[string]*Contract, err
 	return
 }
 
-func ExtractInfo(contract *Contract, filename string) (contenthash common.Hash, err error) {
-	contractInfo, err := json.Marshal(contract.Info)
+func SaveInfo(info *ContractInfo, filename string) (contenthash common.Hash, err error) {
+	infojson, err := json.Marshal(info)
 	if err != nil {
 		return
 	}
-	contenthash = common.BytesToHash(crypto.Sha3(contractInfo))
-	err = ioutil.WriteFile(filename, contractInfo, 0600)
+	contenthash = common.BytesToHash(crypto.Sha3(infojson))
+	err = ioutil.WriteFile(filename, infojson, 0600)
 	return
 }
diff --git a/common/compiler/solidity_test.go b/common/compiler/solidity_test.go
index 59b6b6cd66e432802105d5294a2f8785a2827046..b493d6be351c1398836ecc748ae416969f40f235 100644
--- a/common/compiler/solidity_test.go
+++ b/common/compiler/solidity_test.go
@@ -72,19 +72,15 @@ func TestNoCompiler(t *testing.T) {
 	}
 }
 
-func TestExtractInfo(t *testing.T) {
+func TestSaveInfo(t *testing.T) {
 	var cinfo ContractInfo
 	err := json.Unmarshal([]byte(info), &cinfo)
 	if err != nil {
 		t.Errorf("%v", err)
 	}
-	contract := &Contract{
-		Code: "",
-		Info: cinfo,
-	}
 	filename := "/tmp/solctest.info.json"
 	os.Remove(filename)
-	cinfohash, err := ExtractInfo(contract, filename)
+	cinfohash, err := SaveInfo(&cinfo, filename)
 	if err != nil {
 		t.Errorf("error extracting info: %v", err)
 	}
diff --git a/common/docserver/docserver.go b/common/docserver/docserver.go
index 5e076aa7ee9f1d7951bf5dda99a8ec1723bd348e..6b0cd3130898cdbdbfa106de2154d997f09b3813 100644
--- a/common/docserver/docserver.go
+++ b/common/docserver/docserver.go
@@ -4,34 +4,26 @@ import (
 	"fmt"
 	"io/ioutil"
 	"net/http"
+	"path/filepath"
 
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/crypto"
 )
 
-// http://golang.org/pkg/net/http/#RoundTripper
-var (
-	schemes = map[string]func(*DocServer) http.RoundTripper{
-		// Simple File server from local disk file:///etc/passwd :)
-		"file": fileServerOnDocRoot,
-	}
-)
-
-func fileServerOnDocRoot(ds *DocServer) http.RoundTripper {
-	return http.NewFileTransport(http.Dir(ds.DocRoot))
-}
-
 type DocServer struct {
 	*http.Transport
 	DocRoot string
+	schemes []string
 }
 
-func New(docRoot string) (self *DocServer, err error) {
+func New(docRoot string) (self *DocServer) {
 	self = &DocServer{
 		Transport: &http.Transport{},
 		DocRoot:   docRoot,
+		schemes:   []string{"file"},
 	}
-	err = self.RegisterProtocols(schemes)
+	self.DocRoot = "/tmp/"
+	self.RegisterProtocol("file", http.NewFileTransport(http.Dir(self.DocRoot)))
 	return
 }
 
@@ -45,16 +37,44 @@ func (self *DocServer) Client() *http.Client {
 	}
 }
 
-func (self *DocServer) RegisterProtocols(schemes map[string]func(*DocServer) http.RoundTripper) (err error) {
-	for scheme, rtf := range schemes {
-		self.RegisterProtocol(scheme, rtf(self))
+func (self *DocServer) RegisterScheme(scheme string, rt http.RoundTripper) {
+	self.schemes = append(self.schemes, scheme)
+	self.RegisterProtocol(scheme, rt)
+}
+
+func (self *DocServer) HasScheme(scheme string) bool {
+	for _, s := range self.schemes {
+		if s == scheme {
+			return true
+		}
 	}
-	return
+	return false
 }
 
 func (self *DocServer) GetAuthContent(uri string, hash common.Hash) (content []byte, err error) {
+	// retrieve content
+	content, err = self.Get(uri, "")
+	if err != nil {
+		return
+	}
+
+	// check hash to authenticate content
+	chash := crypto.Sha3Hash(content)
+	if chash != hash {
+		content = nil
+		err = fmt.Errorf("content hash mismatch %x != %x (exp)", hash[:], chash[:])
+	}
+
+	return
+
+}
+
+// Get(uri, path) downloads the document at uri, if path is non-empty it
+// is interpreted as a filepath to which the contents are saved
+func (self *DocServer) Get(uri, path string) (content []byte, err error) {
 	// retrieve content
 	resp, err := self.Client().Get(uri)
+
 	defer func() {
 		if resp != nil {
 			resp.Body.Close()
@@ -68,13 +88,10 @@ func (self *DocServer) GetAuthContent(uri string, hash common.Hash) (content []b
 		return
 	}
 
-	// check hash to authenticate content
-	hashbytes := crypto.Sha3(content)
-	var chash common.Hash
-	copy(chash[:], hashbytes)
-	if chash != hash {
-		content = nil
-		err = fmt.Errorf("content hash mismatch")
+	if path != "" {
+		var abspath string
+		abspath, err = filepath.Abs(path)
+		ioutil.WriteFile(abspath, content, 0700)
 	}
 
 	return
diff --git a/common/docserver/docserver_test.go b/common/docserver/docserver_test.go
index 400d7447ac86adf4c3b3c13f0010745370e4ac99..ca126071c72b204c78b54830788c9eebedeb4965 100644
--- a/common/docserver/docserver_test.go
+++ b/common/docserver/docserver_test.go
@@ -2,6 +2,7 @@ package docserver
 
 import (
 	"io/ioutil"
+	"net/http"
 	"os"
 	"testing"
 
@@ -15,7 +16,7 @@ func TestGetAuthContent(t *testing.T) {
 	copy(hash[:], crypto.Sha3([]byte(text)))
 	ioutil.WriteFile("/tmp/test.content", []byte(text), os.ModePerm)
 
-	ds, err := New("/tmp/")
+	ds := New("/tmp/")
 	content, err := ds.GetAuthContent("file:///test.content", hash)
 	if err != nil {
 		t.Errorf("no error expected, got %v", err)
@@ -26,7 +27,7 @@ func TestGetAuthContent(t *testing.T) {
 
 	hash = common.Hash{}
 	content, err = ds.GetAuthContent("file:///test.content", hash)
-	expected := "content hash mismatch"
+	expected := "content hash mismatch 0000000000000000000000000000000000000000000000000000000000000000 != 9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658 (exp)"
 	if err == nil {
 		t.Errorf("expected error, got nothing")
 	} else {
@@ -36,3 +37,18 @@ func TestGetAuthContent(t *testing.T) {
 	}
 
 }
+
+type rt struct{}
+
+func (rt) RoundTrip(req *http.Request) (resp *http.Response, err error) { return }
+
+func TestRegisterScheme(t *testing.T) {
+	ds := New("/tmp/")
+	if ds.HasScheme("scheme") {
+		t.Errorf("expected scheme not to be registered")
+	}
+	ds.RegisterScheme("scheme", rt{})
+	if !ds.HasScheme("scheme") {
+		t.Errorf("expected scheme to be registered")
+	}
+}
diff --git a/common/natspec/natspec.go b/common/natspec/natspec.go
index 7e5f053c7057da4cadd0b03573a7e75fe911f75e..9965a2227ad56a4372baee6772b846aea6a7918d 100644
--- a/common/natspec/natspec.go
+++ b/common/natspec/natspec.go
@@ -9,7 +9,7 @@ import (
 
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/common/docserver"
-	"github.com/ethereum/go-ethereum/common/resolver"
+	"github.com/ethereum/go-ethereum/common/registrar"
 	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/xeth"
 )
@@ -88,7 +88,7 @@ func New(xeth *xeth.XEth, jsontx string, http *docserver.DocServer) (self *NatSp
 }
 
 // also called by admin.contractInfo.get
-func FetchDocsForContract(contractAddress string, xeth *xeth.XEth, http *docserver.DocServer) (content []byte, err error) {
+func FetchDocsForContract(contractAddress string, xeth *xeth.XEth, ds *docserver.DocServer) (content []byte, err error) {
 	// retrieve contract hash from state
 	codehex := xeth.CodeAt(contractAddress)
 	codeb := xeth.CodeAtBytes(contractAddress)
@@ -99,20 +99,32 @@ func FetchDocsForContract(contractAddress string, xeth *xeth.XEth, http *docserv
 	}
 	codehash := common.BytesToHash(crypto.Sha3(codeb))
 	// set up nameresolver with natspecreg + urlhint contract addresses
-	res := resolver.New(xeth)
+	reg := registrar.New(xeth)
 
 	// resolve host via HashReg/UrlHint Resolver
-	uri, hash, err := res.KeyToUrl(codehash)
+	hash, err := reg.HashToHash(codehash)
 	if err != nil {
 		return
 	}
+	if ds.HasScheme("bzz") {
+		content, err = ds.Get("bzz://"+hash.Hex()[2:], "")
+		if err == nil { // non-fatal
+			return
+		}
+		err = nil
+		//falling back to urlhint
+	}
 
-	// get content via http client and authenticate content using hash
-	content, err = http.GetAuthContent(uri, hash)
+	uri, err := reg.HashToUrl(hash)
 	if err != nil {
 		return
 	}
 
+	// get content via http client and authenticate content using hash
+	content, err = ds.GetAuthContent(uri, hash)
+	if err != nil {
+		return
+	}
 	return
 }
 
diff --git a/common/natspec/natspec_e2e_test.go b/common/natspec/natspec_e2e_test.go
index 7e9172649662c7505872ffc8da7a7e76ba75ba68..db5ef2527d4899239e17f3a26028ddd04aa51f59 100644
--- a/common/natspec/natspec_e2e_test.go
+++ b/common/natspec/natspec_e2e_test.go
@@ -3,16 +3,18 @@ package natspec
 import (
 	"fmt"
 	"io/ioutil"
+	"math/big"
 	"os"
+	"runtime"
 	"strings"
 	"testing"
+	"time"
 
 	"github.com/ethereum/go-ethereum/accounts"
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/common/docserver"
-	"github.com/ethereum/go-ethereum/common/resolver"
+	"github.com/ethereum/go-ethereum/common/registrar"
 	"github.com/ethereum/go-ethereum/core"
-	"github.com/ethereum/go-ethereum/core/state"
 	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/eth"
 	xe "github.com/ethereum/go-ethereum/xeth"
@@ -73,13 +75,10 @@ const (
 )
 
 type testFrontend struct {
-	t *testing.T
-	// resolver    *resolver.Resolver
+	t           *testing.T
 	ethereum    *eth.Ethereum
 	xeth        *xe.XEth
-	coinbase    common.Address
-	stateDb     *state.StateDB
-	txc         uint64
+	wait        chan *big.Int
 	lastConfirm string
 	wantNatSpec bool
 }
@@ -91,10 +90,7 @@ func (self *testFrontend) UnlockAccount(acc []byte) bool {
 
 func (self *testFrontend) ConfirmTransaction(tx string) bool {
 	if self.wantNatSpec {
-		ds, err := docserver.New("/tmp/")
-		if err != nil {
-			self.t.Errorf("Error creating DocServer: %v", err)
-		}
+		ds := docserver.New("/tmp/")
 		self.lastConfirm = GetNotice(self.xeth, tx, ds)
 	}
 	return true
@@ -128,6 +124,8 @@ func testEth(t *testing.T) (ethereum *eth.Ethereum, err error) {
 		DataDir:        "/tmp/eth-natspec",
 		AccountManager: am,
 		MaxPeers:       0,
+		PowTest:        true,
+		Etherbase:      testAddress,
 	})
 
 	if err != nil {
@@ -153,30 +151,41 @@ func testInit(t *testing.T) (self *testFrontend) {
 	// mock frontend
 	self = &testFrontend{t: t, ethereum: ethereum}
 	self.xeth = xe.New(ethereum, self)
-
-	addr, _ := ethereum.Etherbase()
-	self.coinbase = addr
-	self.stateDb = self.ethereum.ChainManager().State().Copy()
+	self.wait = self.xeth.UpdateState()
+	addr, _ := self.ethereum.Etherbase()
 
 	// initialise the registry contracts
-	// self.resolver.CreateContracts(addr)
-	resolver.New(self.xeth).CreateContracts(addr)
-	self.applyTxs()
-	// t.Logf("HashReg contract registered at %v", resolver.HashRegContractAddress)
-	// t.Logf("URLHint contract registered at %v", resolver.UrlHintContractAddress)
+	reg := registrar.New(self.xeth)
+	var registrarTxhash, hashRegTxhash, urlHintTxhash string
+	registrarTxhash, err = reg.SetGlobalRegistrar("", addr)
+	if err != nil {
+		t.Errorf("error creating GlobalRegistrar: %v", err)
+	}
 
-	return
+	hashRegTxhash, err = reg.SetHashReg("", addr)
+	if err != nil {
+		t.Errorf("error creating HashReg: %v", err)
+	}
+	urlHintTxhash, err = reg.SetUrlHint("", addr)
+	if err != nil {
+		t.Errorf("error creating UrlHint: %v", err)
+	}
+	if !processTxs(self, t, 3) {
+		t.Errorf("error mining txs")
+	}
+	_ = registrarTxhash
+	_ = hashRegTxhash
+	_ = urlHintTxhash
 
-}
+	/* TODO:
+	* lookup receipt and contract addresses by tx hash
+	* name registration for HashReg and UrlHint addresses
+	* mine those transactions
+	* then set once more SetHashReg SetUrlHint
+	 */
 
-// this is needed for transaction to be applied to the state in testing
-// the heavy lifing is done in XEth.ApplyTestTxs
-// this is fragile,
-// and does process leaking since xeth loops cannot quit safely
-// should be replaced by proper mining with testDAG for easy full integration tests
-func (self *testFrontend) applyTxs() {
-	self.txc, self.xeth = self.xeth.ApplyTestTxs(self.stateDb, self.coinbase, self.txc)
 	return
+
 }
 
 // end to end test
@@ -185,54 +194,63 @@ func TestNatspecE2E(t *testing.T) {
 
 	tf := testInit(t)
 	defer tf.ethereum.Stop()
+	addr, _ := tf.ethereum.Etherbase()
 
 	// create a contractInfo file (mock cloud-deployed contract metadocs)
 	// incidentally this is the info for the registry contract itself
 	ioutil.WriteFile("/tmp/"+testFileName, []byte(testContractInfo), os.ModePerm)
-	dochash := common.BytesToHash(crypto.Sha3([]byte(testContractInfo)))
+	dochash := crypto.Sha3Hash([]byte(testContractInfo))
 
 	// take the codehash for the contract we wanna test
-	// codehex := tf.xeth.CodeAt(resolver.HashRegContractAddress)
-	codeb := tf.xeth.CodeAtBytes(resolver.HashRegContractAddress)
-	codehash := common.BytesToHash(crypto.Sha3(codeb))
+	codeb := tf.xeth.CodeAtBytes(registrar.HashRegAddr)
+	codehash := crypto.Sha3Hash(codeb)
 
 	// use resolver to register codehash->dochash->url
-	registry := resolver.New(tf.xeth)
-	_, err := registry.Register(tf.coinbase, codehash, dochash, "file:///"+testFileName)
+	// test if globalregistry works
+	// registrar.HashRefAddr = "0x0"
+	// registrar.UrlHintAddr = "0x0"
+	reg := registrar.New(tf.xeth)
+	_, err := reg.SetHashToHash(addr, codehash, dochash)
 	if err != nil {
 		t.Errorf("error registering: %v", err)
 	}
-	// apply txs to the state
-	tf.applyTxs()
+	_, err = reg.SetUrlToHash(addr, dochash, "file:///"+testFileName)
+	if err != nil {
+		t.Errorf("error registering: %v", err)
+	}
+	if !processTxs(tf, t, 5) {
+		return
+	}
 
 	// NatSpec info for register method of HashReg contract installed
 	// now using the same transactions to check confirm messages
 
 	tf.wantNatSpec = true // this is set so now the backend uses natspec confirmation
-	_, err = registry.RegisterContentHash(tf.coinbase, codehash, dochash)
+	_, err = reg.SetHashToHash(addr, codehash, dochash)
 	if err != nil {
 		t.Errorf("error calling contract registry: %v", err)
 	}
 
+	fmt.Printf("GlobalRegistrar: %v, HashReg: %v, UrlHint: %v\n", registrar.GlobalRegistrarAddr, registrar.HashRegAddr, registrar.UrlHintAddr)
 	if tf.lastConfirm != testExpNotice {
-		t.Errorf("Wrong confirm message. expected '%v', got '%v'", testExpNotice, tf.lastConfirm)
+		t.Errorf("Wrong confirm message. expected\n'%v', got\n'%v'", testExpNotice, tf.lastConfirm)
 	}
 
 	// test unknown method
-	exp := fmt.Sprintf(testExpNotice2, resolver.HashRegContractAddress)
-	_, err = registry.SetOwner(tf.coinbase)
+	exp := fmt.Sprintf(testExpNotice2, registrar.HashRegAddr)
+	_, err = reg.SetOwner(addr)
 	if err != nil {
 		t.Errorf("error setting owner: %v", err)
 	}
 
 	if tf.lastConfirm != exp {
-		t.Errorf("Wrong confirm message, expected '%v', got '%v'", exp, tf.lastConfirm)
+		t.Errorf("Wrong confirm message, expected\n'%v', got\n'%v'", exp, tf.lastConfirm)
 	}
 
 	// test unknown contract
-	exp = fmt.Sprintf(testExpNotice3, resolver.UrlHintContractAddress)
+	exp = fmt.Sprintf(testExpNotice3, registrar.UrlHintAddr)
 
-	_, err = registry.RegisterUrl(tf.coinbase, dochash, "file:///test.content")
+	_, err = reg.SetUrlToHash(addr, dochash, "file:///test.content")
 	if err != nil {
 		t.Errorf("error registering: %v", err)
 	}
@@ -242,3 +260,63 @@ func TestNatspecE2E(t *testing.T) {
 	}
 
 }
+
+func pendingTransactions(repl *testFrontend, t *testing.T) (txc int64, err error) {
+	txs := repl.ethereum.TxPool().GetTransactions()
+	return int64(len(txs)), nil
+}
+
+func processTxs(repl *testFrontend, t *testing.T, expTxc int) bool {
+	var txc int64
+	var err error
+	for i := 0; i < 50; i++ {
+		txc, err = pendingTransactions(repl, t)
+		if err != nil {
+			t.Errorf("unexpected error checking pending transactions: %v", err)
+			return false
+		}
+		if expTxc < int(txc) {
+			t.Errorf("too many pending transactions: expected %v, got %v", expTxc, txc)
+			return false
+		} else if expTxc == int(txc) {
+			break
+		}
+		time.Sleep(100 * time.Millisecond)
+	}
+	if int(txc) != expTxc {
+		t.Errorf("incorrect number of pending transactions, expected %v, got %v", expTxc, txc)
+		return false
+	}
+
+	err = repl.ethereum.StartMining(runtime.NumCPU())
+	if err != nil {
+		t.Errorf("unexpected error mining: %v", err)
+		return false
+	}
+	defer repl.ethereum.StopMining()
+
+	timer := time.NewTimer(100 * time.Second)
+	height := new(big.Int).Add(repl.xeth.CurrentBlock().Number(), big.NewInt(1))
+	repl.wait <- height
+	select {
+	case <-timer.C:
+		// if times out make sure the xeth loop does not block
+		go func() {
+			select {
+			case repl.wait <- nil:
+			case <-repl.wait:
+			}
+		}()
+	case <-repl.wait:
+	}
+	txc, err = pendingTransactions(repl, t)
+	if err != nil {
+		t.Errorf("unexpected error checking pending transactions: %v", err)
+		return false
+	}
+	if txc != 0 {
+		t.Errorf("%d trasactions were not mined", txc)
+		return false
+	}
+	return true
+}
diff --git a/common/natspec/natspec_e2e_test.go.orig b/common/natspec/natspec_e2e_test.go.orig
new file mode 100644
index 0000000000000000000000000000000000000000..ae8e17ad9ad9a5297ffa473256df4c1cc2e47f7f
--- /dev/null
+++ b/common/natspec/natspec_e2e_test.go.orig
@@ -0,0 +1,253 @@
+package natspec
+
+import (
+  "fmt"
+  "io/ioutil"
+  "os"
+  "strings"
+  "testing"
+
+  "github.com/ethereum/go-ethereum/accounts"
+  "github.com/ethereum/go-ethereum/common"
+  "github.com/ethereum/go-ethereum/common/docserver"
+  "github.com/ethereum/go-ethereum/common/registrar"
+  "github.com/ethereum/go-ethereum/core"
+  "github.com/ethereum/go-ethereum/core/state"
+  "github.com/ethereum/go-ethereum/crypto"
+  "github.com/ethereum/go-ethereum/eth"
+  xe "github.com/ethereum/go-ethereum/xeth"
+)
+
+const (
+  testBalance = "10000000000000000000"
+
+  testFileName = "long_file_name_for_testing_registration_of_URLs_longer_than_32_bytes.content"
+
+  testNotice = "Register key `utils.toHex(_key)` <- content `utils.toHex(_content)`"
+
+  testExpNotice = "Register key 0xadd1a7d961cff0242089674ec2ef6fca671ab15e1fe80e38859fc815b98d88ab <- content 0xb3a2dea218de5d8bbe6c4645aadbf67b5ab00ecb1a9ec95dbdad6a0eed3e41a7"
+
+  testExpNotice2 = `About to submit transaction (NatSpec notice error: abi key does not match any method): {"params":[{"to":"%s","data": "0x31e12c20"}]}`
+
+  testExpNotice3 = `About to submit transaction (no NatSpec info found for contract: content hash not found for '0x1392c62d05b2d149e22a339c531157ae06b44d39a674cce500064b12b9aeb019'): {"params":[{"to":"%s","data": "0x300a3bbfb3a2dea218de5d8bbe6c4645aadbf67b5ab00ecb1a9ec95dbdad6a0eed3e41a7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066696c653a2f2f2f746573742e636f6e74656e74"}]}`
+)
+
+const (
+  testUserDoc = `
+{
+  "methods": {
+    "register(uint256,uint256)": {
+      "notice":  "` + testNotice + `"
+    }
+  },
+  "invariants": [
+    { "notice": "" }
+  ],
+  "construction": [
+    { "notice": "" }
+  ]
+}
+`
+  testAbiDefinition = `
+[{
+  "name": "register",
+  "constant": false,
+  "type": "function",
+  "inputs": [{
+    "name": "_key",
+    "type": "uint256"
+  }, {
+    "name": "_content",
+    "type": "uint256"
+  }],
+  "outputs": []
+}]
+`
+
+  testContractInfo = `
+{
+  "userDoc": ` + testUserDoc + `,
+  "abiDefinition": ` + testAbiDefinition + `
+}
+`
+)
+
+type testFrontend struct {
+  t           *testing.T
+  ethereum    *eth.Ethereum
+  xeth        *xe.XEth
+  coinbase    common.Address
+  stateDb     *state.StateDB
+  txc         uint64
+  lastConfirm string
+  wantNatSpec bool
+}
+
+func (self *testFrontend) UnlockAccount(acc []byte) bool {
+  self.ethereum.AccountManager().Unlock(common.BytesToAddress(acc), "password")
+  return true
+}
+
+func (self *testFrontend) ConfirmTransaction(tx string) bool {
+  if self.wantNatSpec {
+    ds := docserver.New("/tmp/")
+    self.lastConfirm = GetNotice(self.xeth, tx, ds)
+  }
+  return true
+}
+
+func testEth(t *testing.T) (ethereum *eth.Ethereum, err error) {
+
+  os.RemoveAll("/tmp/eth-natspec/")
+
+  err = os.MkdirAll("/tmp/eth-natspec/keystore", os.ModePerm)
+  if err != nil {
+    panic(err)
+  }
+
+  // create a testAddress
+  ks := crypto.NewKeyStorePassphrase("/tmp/eth-natspec/keystore")
+  am := accounts.NewManager(ks)
+  testAccount, err := am.NewAccount("password")
+  if err != nil {
+    panic(err)
+  }
+  testAddress := strings.TrimPrefix(testAccount.Address.Hex(), "0x")
+
+  // set up mock genesis with balance on the testAddress
+  core.GenesisAccounts = []byte(`{
+  "` + testAddress + `": {"balance": "` + testBalance + `"}
+  }`)
+
+  // only use minimalistic stack with no networking
+  ethereum, err = eth.New(&eth.Config{
+    DataDir:        "/tmp/eth-natspec",
+    AccountManager: am,
+    MaxPeers:       0,
+  })
+
+  if err != nil {
+    panic(err)
+  }
+
+  return
+}
+
+func testInit(t *testing.T) (self *testFrontend) {
+  // initialise and start minimal ethereum stack
+  ethereum, err := testEth(t)
+  if err != nil {
+    t.Errorf("error creating ethereum: %v", err)
+    return
+  }
+  err = ethereum.Start()
+  if err != nil {
+    t.Errorf("error starting ethereum: %v", err)
+    return
+  }
+
+  // mock frontend
+  self = &testFrontend{t: t, ethereum: ethereum}
+  self.xeth = xe.New(ethereum, self)
+
+  addr, _ := ethereum.Etherbase()
+  self.coinbase = addr
+  self.stateDb = self.ethereum.ChainManager().State().Copy()
+
+  // initialise the registry contracts
+  reg := registrar.New(self.xeth)
+  err = reg.SetHashReg("", addr)
+  if err != nil {
+    t.Errorf("error creating HashReg: %v", err)
+  }
+  err = reg.SetUrlHint("", addr)
+  if err != nil {
+    t.Errorf("error creating UrlHint: %v", err)
+  }
+  self.applyTxs()
+
+  return
+
+}
+
+// this is needed for transaction to be applied to the state in testing
+// the heavy lifing is done in XEth.ApplyTestTxs
+// this is fragile,
+// and does process leaking since xeth loops cannot quit safely
+// should be replaced by proper mining with testDAG for easy full integration tests
+func (self *testFrontend) applyTxs() {
+  self.txc, self.xeth = self.xeth.ApplyTestTxs(self.stateDb, self.coinbase, self.txc)
+  return
+}
+
+// end to end test
+func TestNatspecE2E(t *testing.T) {
+  t.Skip()
+
+  tf := testInit(t)
+  defer tf.ethereum.Stop()
+
+  // create a contractInfo file (mock cloud-deployed contract metadocs)
+  // incidentally this is the info for the registry contract itself
+  ioutil.WriteFile("/tmp/"+testFileName, []byte(testContractInfo), os.ModePerm)
+  dochash := common.BytesToHash(crypto.Sha3([]byte(testContractInfo)))
+
+  // take the codehash for the contract we wanna test
+  // codehex := tf.xeth.CodeAt(registar.HashRegAddr)
+  codeb := tf.xeth.CodeAtBytes(registrar.HashRegAddr)
+  codehash := common.BytesToHash(crypto.Sha3(codeb))
+
+  // use resolver to register codehash->dochash->url
+  // test if globalregistry works
+  // registrar.HashRefAddr = "0x0"
+  // registrar.UrlHintAddr = "0x0"
+  reg := registrar.New(tf.xeth)
+  _, err := reg.SetHashToHash(tf.coinbase, codehash, dochash)
+  if err != nil {
+    t.Errorf("error registering: %v", err)
+  }
+  _, err = reg.SetUrlToHash(tf.coinbase, dochash, "file:///"+testFileName)
+  if err != nil {
+    t.Errorf("error registering: %v", err)
+  }
+  // apply txs to the state
+  tf.applyTxs()
+
+  // NatSpec info for register method of HashReg contract installed
+  // now using the same transactions to check confirm messages
+
+  tf.wantNatSpec = true // this is set so now the backend uses natspec confirmation
+  _, err = reg.SetHashToHash(tf.coinbase, codehash, dochash)
+  if err != nil {
+    t.Errorf("error calling contract registry: %v", err)
+  }
+
+  fmt.Printf("GlobalRegistrar: %v, HashReg: %v, UrlHint: %v\n", registrar.GlobalRegistrarAddr, registrar.HashRegAddr, registrar.UrlHintAddr)
+  if tf.lastConfirm != testExpNotice {
+    t.Errorf("Wrong confirm message. expected '%v', got '%v'", testExpNotice, tf.lastConfirm)
+  }
+
+  // test unknown method
+  exp := fmt.Sprintf(testExpNotice2, registrar.HashRegAddr)
+  _, err = reg.SetOwner(tf.coinbase)
+  if err != nil {
+    t.Errorf("error setting owner: %v", err)
+  }
+
+  if tf.lastConfirm != exp {
+    t.Errorf("Wrong confirm message, expected '%v', got '%v'", exp, tf.lastConfirm)
+  }
+
+  // test unknown contract
+  exp = fmt.Sprintf(testExpNotice3, registrar.UrlHintAddr)
+
+  _, err = reg.SetUrlToHash(tf.coinbase, dochash, "file:///test.content")
+  if err != nil {
+    t.Errorf("error registering: %v", err)
+  }
+
+  if tf.lastConfirm != exp {
+    t.Errorf("Wrong confirm message, expected '%v', got '%v'", exp, tf.lastConfirm)
+  }
+
+}
diff --git a/common/registrar/contracts.go b/common/registrar/contracts.go
new file mode 100644
index 0000000000000000000000000000000000000000..6c624030ef36bd44edf96a256900dad848d345a2
--- /dev/null
+++ b/common/registrar/contracts.go
@@ -0,0 +1,147 @@
+package registrar
+
+const ( // built-in contracts address source code and evm code
+	UrlHintCode = "0x60c180600c6000396000f30060003560e060020a90048063300a3bbf14601557005b6024600435602435604435602a565b60006000f35b6000600084815260200190815260200160002054600160a060020a0316600014806078575033600160a060020a03166000600085815260200190815260200160002054600160a060020a0316145b607f5760bc565b336000600085815260200190815260200160002081905550806001600085815260200190815260200160002083610100811060b657005b01819055505b50505056"
+
+	UrlHintSrc = `
+contract URLhint {
+	function register(uint256 _hash, uint8 idx, uint256 _url) {
+		if (owner[_hash] == 0 || owner[_hash] == msg.sender) {
+			owner[_hash] = msg.sender;
+			url[_hash][idx] = _url;
+		}
+	}
+	mapping (uint256 => address) owner;
+	  (uint256 => uint256[256]) url;
+}
+	`
+
+	HashRegCode = "0x609880600c6000396000f30060003560e060020a9004806331e12c2014601f578063d66d6c1014602b57005b6025603d565b60006000f35b6037600435602435605d565b60006000f35b600054600160a060020a0316600014605357605b565b336000819055505b565b600054600160a060020a031633600160a060020a031614607b576094565b8060016000848152602001908152602001600020819055505b505056"
+
+	HashRegSrc = `
+contract HashReg {
+	function setowner() {
+		if (owner == 0) {
+			owner = msg.sender;
+		}
+	}
+	function register(uint256 _key, uint256 _content) {
+		if (msg.sender == owner) {
+			content[_key] = _content;
+  	}
+	}
+	address owner;
+	mapping (uint256 => uint256) content;
+}
+`
+
+	GlobalRegistrarSrc = `
+//sol
+
+import "owned";
+
+contract NameRegister {
+  function addr(bytes32 _name) constant returns (address o_owner) {}
+  function name(address _owner) constant returns (bytes32 o_name) {}
+}
+
+contract Registrar is NameRegister {
+  event Changed(bytes32 indexed name);
+  event PrimaryChanged(bytes32 indexed name, address indexed addr);
+
+  function owner(bytes32 _name) constant returns (address o_owner) {}
+  function addr(bytes32 _name) constant returns (address o_address) {}
+  function subRegistrar(bytes32 _name) constant returns (address o_subRegistrar) {}
+  function content(bytes32 _name) constant returns (bytes32 o_content) {}
+
+  function name(address _owner) constant returns (bytes32 o_name) {}
+}
+
+contract GlobalRegistrar is Registrar {
+  struct Record {
+    address owner;
+    address primary;
+    address subRegistrar;
+    bytes32 content;
+    uint value;
+    uint renewalDate;
+  }
+
+  function Registrar() {
+    // TODO: Populate with hall-of-fame.
+  }
+
+  function reserve(bytes32 _name) {
+    // Don't allow the same name to be overwritten.
+    // TODO: bidding mechanism
+    if (m_toRecord[_name].owner == 0) {
+      m_toRecord[_name].owner = msg.sender;
+      Changed(_name);
+    }
+  }
+
+  /*
+  TODO
+  > 12 chars: free
+  <= 12 chars: auction:
+  1. new names are auctioned
+  - 7 day period to collect all bid bytes32es + deposits
+  - 1 day period to collect all bids to be considered (validity requires associated deposit to be >10% of bid)
+  - all valid bids are burnt except highest - difference between that and second highest is returned to winner
+  2. remember when last auctioned/renewed
+  3. anyone can force renewal process:
+  - 7 day period to collect all bid bytes32es + deposits
+  - 1 day period to collect all bids & full amounts - bids only uncovered if sufficiently high.
+  - 1% of winner burnt; original owner paid rest.
+  */
+
+  modifier onlyrecordowner(bytes32 _name) { if (m_toRecord[_name].owner == msg.sender) _ }
+
+  function transfer(bytes32 _name, address _newOwner) onlyrecordowner(_name) {
+    m_toRecord[_name].owner = _newOwner;
+    Changed(_name);
+  }
+
+  function disown(bytes32 _name) onlyrecordowner(_name) {
+    if (m_toName[m_toRecord[_name].primary] == _name)
+    {
+      PrimaryChanged(_name, m_toRecord[_name].primary);
+      m_toName[m_toRecord[_name].primary] = "";
+    }
+    delete m_toRecord[_name];
+    Changed(_name);
+  }
+
+  function setAddress(bytes32 _name, address _a, bool _primary) onlyrecordowner(_name) {
+    m_toRecord[_name].primary = _a;
+    if (_primary)
+    {
+      PrimaryChanged(_name, _a);
+      m_toName[_a] = _name;
+    }
+    Changed(_name);
+  }
+  function setSubRegistrar(bytes32 _name, address _registrar) onlyrecordowner(_name) {
+    m_toRecord[_name].subRegistrar = _registrar;
+    Changed(_name);
+  }
+  function setContent(bytes32 _name, bytes32 _content) onlyrecordowner(_name) {
+    m_toRecord[_name].content = _content;
+    Changed(_name);
+  }
+
+  function owner(bytes32 _name) constant returns (address) { return m_toRecord[_name].owner; }
+  function addr(bytes32 _name) constant returns (address) { return m_toRecord[_name].primary; }
+//  function subRegistrar(bytes32 _name) constant returns (address) { return m_toRecord[_name].subRegistrar; } // TODO: bring in on next iteration.
+  function register(bytes32 _name) constant returns (address) { return m_toRecord[_name].subRegistrar; }  // only possible for now
+  function content(bytes32 _name) constant returns (bytes32) { return m_toRecord[_name].content; }
+  function name(address _owner) constant returns (bytes32 o_name) { return m_toName[_owner]; }
+
+  mapping (address => bytes32) m_toName;
+  mapping (bytes32 => Record) m_toRecord;
+}
+`
+	GlobalRegistrarAbi = `[{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"name","outputs":[{"name":"o_name","type":"bytes32"}],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"content","outputs":[{"name":"","type":"bytes32"}],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"addr","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserve","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"subRegistrar","outputs":[{"name":"o_subRegistrar","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_newOwner","type":"address"}],"name":"transfer","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_registrar","type":"address"}],"name":"setSubRegistrar","outputs":[],"type":"function"},{"constant":false,"inputs":[],"name":"Registrar","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_a","type":"address"},{"name":"_primary","type":"bool"}],"name":"setAddress","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_content","type":"bytes32"}],"name":"setContent","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"disown","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"register","outputs":[{"name":"","type":"address"}],"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"}],"name":"Changed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"addr","type":"address"}],"name":"PrimaryChanged","type":"event"}]`
+
+	GlobalRegistrarCode = `0x610b408061000e6000396000f3006000357c01000000000000000000000000000000000000000000000000000000009004806301984892146100b357806302571be3146100ce5780632dff6941146100ff5780633b3b57de1461011a578063432ced041461014b5780635a3a05bd1461016257806379ce9fac1461019357806389a69c0e146101b0578063b9f37c86146101cd578063be99a980146101de578063c3d014d614610201578063d93e75731461021e578063e1fa8e841461023557005b6100c4600480359060200150610b02565b8060005260206000f35b6100df6004803590602001506109f3565b8073ffffffffffffffffffffffffffffffffffffffff1660005260206000f35b610110600480359060200150610ad4565b8060005260206000f35b61012b600480359060200150610a3e565b8073ffffffffffffffffffffffffffffffffffffffff1660005260206000f35b61015c600480359060200150610271565b60006000f35b610173600480359060200150610266565b8073ffffffffffffffffffffffffffffffffffffffff1660005260206000f35b6101aa600480359060200180359060200150610341565b60006000f35b6101c7600480359060200180359060200150610844565b60006000f35b6101d860045061026e565b60006000f35b6101fb6004803590602001803590602001803590602001506106de565b60006000f35b61021860048035906020018035906020015061092c565b60006000f35b61022f600480359060200150610429565b60006000f35b610246600480359060200150610a89565b8073ffffffffffffffffffffffffffffffffffffffff1660005260206000f35b60005b919050565b5b565b60006001600050600083815260200190815260200160002060005060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561033d57336001600050600083815260200190815260200160002060005060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff02191690830217905550807fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc6040604090036040a25b5b50565b813373ffffffffffffffffffffffffffffffffffffffff166001600050600083815260200190815260200160002060005060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561042357816001600050600085815260200190815260200160002060005060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff02191690830217905550827fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc6040604090036040a25b505b5050565b803373ffffffffffffffffffffffffffffffffffffffff166001600050600083815260200190815260200160002060005060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156106d95781600060005060006001600050600086815260200190815260200160002060005060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000505414156105fd576001600050600083815260200190815260200160002060005060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16827ff63780e752c6a54a94fc52715dbc5518a3b4c3c2833d301a204226548a2a85456040604090036040a36000600060005060006001600050600086815260200190815260200160002060005060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600050819055505b6001600050600083815260200190815260200160002060006000820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556002820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556003820160005060009055600482016000506000905560058201600050600090555050817fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc6040604090036040a25b505b50565b823373ffffffffffffffffffffffffffffffffffffffff166001600050600083815260200190815260200160002060005060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561083d57826001600050600086815260200190815260200160002060005060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055508115610811578273ffffffffffffffffffffffffffffffffffffffff16847ff63780e752c6a54a94fc52715dbc5518a3b4c3c2833d301a204226548a2a85456040604090036040a383600060005060008573ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600050819055505b837fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc6040604090036040a25b505b505050565b813373ffffffffffffffffffffffffffffffffffffffff166001600050600083815260200190815260200160002060005060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561092657816001600050600085815260200190815260200160002060005060020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff02191690830217905550827fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc6040604090036040a25b505b5050565b813373ffffffffffffffffffffffffffffffffffffffff166001600050600083815260200190815260200160002060005060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156109ed57816001600050600085815260200190815260200160002060005060030160005081905550827fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc6040604090036040a25b505b5050565b60006001600050600083815260200190815260200160002060005060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050610a39565b919050565b60006001600050600083815260200190815260200160002060005060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050610a84565b919050565b60006001600050600083815260200190815260200160002060005060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050610acf565b919050565b600060016000506000838152602001908152602001600020600050600301600050549050610afd565b919050565b6000600060005060008373ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600050549050610b3b565b91905056`
+)
diff --git a/common/registrar/ethreg/ethreg.go b/common/registrar/ethreg/ethreg.go
new file mode 100644
index 0000000000000000000000000000000000000000..f5ad3345bfb8dde94bfe1630b03e54981a112375
--- /dev/null
+++ b/common/registrar/ethreg/ethreg.go
@@ -0,0 +1,32 @@
+package ethreg
+
+import (
+	"math/big"
+
+	"github.com/ethereum/go-ethereum/common/registrar"
+	"github.com/ethereum/go-ethereum/xeth"
+)
+
+// implements a versioned Registrar on an archiving full node
+type EthReg struct {
+	backend  *xeth.XEth
+	registry *registrar.Registrar
+}
+
+func New(xe *xeth.XEth) (self *EthReg) {
+	self = &EthReg{backend: xe}
+	self.registry = registrar.New(xe)
+	return
+}
+
+func (self *EthReg) Registry() *registrar.Registrar {
+	return self.registry
+}
+
+func (self *EthReg) Resolver(n *big.Int) *registrar.Registrar {
+	xe := self.backend
+	if n != nil {
+		xe = self.backend.AtStateNum(n.Int64())
+	}
+	return registrar.New(xe)
+}
diff --git a/common/registrar/registrar.go b/common/registrar/registrar.go
new file mode 100644
index 0000000000000000000000000000000000000000..b70c7227bf6e6b8d17a31ca280ae6ba431218967
--- /dev/null
+++ b/common/registrar/registrar.go
@@ -0,0 +1,392 @@
+package registrar
+
+import (
+	"encoding/binary"
+	"fmt"
+	"math/big"
+	"regexp"
+
+	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/crypto"
+	"github.com/ethereum/go-ethereum/logger"
+	"github.com/ethereum/go-ethereum/logger/glog"
+)
+
+/*
+Registrar implements the Ethereum name registrar services mapping
+- arbitrary strings to ethereum addresses
+- hashes to hashes
+- hashes to arbitrary strings
+(likely will provide lookup service for all three)
+
+The Registrar is used by
+* the roundtripper transport implementation of
+url schemes to resolve domain names and services that register these names
+* contract info retrieval (NatSpec).
+
+The Registrar uses 3 contracts on the blockchain:
+* GlobalRegistrar: Name (string) -> Address (Owner)
+* HashReg : Key Hash (hash of domain name or contract code) -> Content Hash
+* UrlHint : Content Hash -> Url Hint
+
+These contracts are (currently) not included in the genesis block.
+Each Set<X> needs to be called once on each blockchain/network once.
+
+Contract addresses need to be set (HashReg and UrlHint retrieved from the global
+registrar the first time any Registrar method is called in a client session
+
+So the caller needs to make sure the relevant environment initialised the desired
+contracts
+*/
+var (
+	UrlHintAddr         = "0x0"
+	HashRegAddr         = "0x0"
+	GlobalRegistrarAddr = "0x0"
+	// GlobalRegistrarAddr = "0xc6d9d2cd449a754c494264e1809c50e34d64562b"
+
+	zero = regexp.MustCompile("^(0x)?0*$")
+)
+
+const (
+	trueHex  = "0000000000000000000000000000000000000000000000000000000000000001"
+	falseHex = "0000000000000000000000000000000000000000000000000000000000000000"
+)
+
+func abiSignature(s string) string {
+	return common.ToHex(crypto.Sha3([]byte(s))[:4])
+}
+
+var (
+	HashRegName = "HashReg"
+	UrlHintName = "UrlHint"
+
+	registerContentHashAbi = abiSignature("register(uint256,uint256)")
+	registerUrlAbi         = abiSignature("register(uint256,uint8,uint256)")
+	setOwnerAbi            = abiSignature("setowner()")
+	reserveAbi             = abiSignature("reserve(bytes32)")
+	resolveAbi             = abiSignature("addr(bytes32)")
+	registerAbi            = abiSignature("setAddress(bytes32,address,bool)")
+	addressAbiPrefix       = falseHex[:24]
+)
+
+// Registrar's backend is defined as an interface (implemented by xeth, but could be remote)
+type Backend interface {
+	StorageAt(string, string) string
+	Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error)
+	Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, string, error)
+}
+
+// TODO Registrar should also just implement The Resolver and Registry interfaces
+// Simplify for now.
+type VersionedRegistrar interface {
+	Resolver(*big.Int) *Registrar
+	Registry() *Registrar
+}
+
+type Registrar struct {
+	backend Backend
+}
+
+func New(b Backend) (res *Registrar) {
+	res = &Registrar{b}
+	return
+}
+
+func (self *Registrar) SetGlobalRegistrar(namereg string, addr common.Address) (txhash string, err error) {
+	if namereg != "" {
+		GlobalRegistrarAddr = namereg
+		return
+	}
+	if GlobalRegistrarAddr == "0x0" || GlobalRegistrarAddr == "0x" {
+		if (addr == common.Address{}) {
+			err = fmt.Errorf("GlobalRegistrar address not found and sender for creation not given")
+			return
+		} else {
+			txhash, err = self.backend.Transact(addr.Hex(), "", "", "", "800000", "", GlobalRegistrarCode)
+			if err != nil {
+				err = fmt.Errorf("GlobalRegistrar address not found and sender for creation failed: %v", err)
+				return
+			}
+		}
+	}
+	return
+}
+
+func (self *Registrar) SetHashReg(hashreg string, addr common.Address) (txhash string, err error) {
+	if hashreg != "" {
+		HashRegAddr = hashreg
+	} else {
+		if !zero.MatchString(HashRegAddr) {
+			return
+		}
+		nameHex, extra := encodeName(HashRegName, 2)
+		hashRegAbi := resolveAbi + nameHex + extra
+		glog.V(logger.Detail).Infof("\ncall HashRegAddr %v with %v\n", GlobalRegistrarAddr, hashRegAbi)
+		var res string
+		res, _, err = self.backend.Call("", GlobalRegistrarAddr, "", "", "", hashRegAbi)
+		if len(res) >= 40 {
+			HashRegAddr = "0x" + res[len(res)-40:len(res)]
+		}
+		if err != nil || zero.MatchString(HashRegAddr) {
+			if (addr == common.Address{}) {
+				err = fmt.Errorf("HashReg address not found and sender for creation not given")
+				return
+			}
+
+			txhash, err = self.backend.Transact(addr.Hex(), "", "", "", "", "", HashRegCode)
+			if err != nil {
+				err = fmt.Errorf("HashReg address not found and sender for creation failed: %v", err)
+			}
+			glog.V(logger.Detail).Infof("created HashRegAddr @ txhash %v\n", txhash)
+		} else {
+			glog.V(logger.Detail).Infof("HashRegAddr found at @ %v\n", HashRegAddr)
+			return
+		}
+	}
+
+	return
+}
+
+func (self *Registrar) SetUrlHint(urlhint string, addr common.Address) (txhash string, err error) {
+	if urlhint != "" {
+		UrlHintAddr = urlhint
+	} else {
+		if !zero.MatchString(UrlHintAddr) {
+			return
+		}
+		nameHex, extra := encodeName(UrlHintName, 2)
+		urlHintAbi := resolveAbi + nameHex + extra
+		glog.V(logger.Detail).Infof("UrlHint address query data: %s to %s", urlHintAbi, GlobalRegistrarAddr)
+		var res string
+		res, _, err = self.backend.Call("", GlobalRegistrarAddr, "", "", "", urlHintAbi)
+		if len(res) >= 40 {
+			UrlHintAddr = "0x" + res[len(res)-40:len(res)]
+		}
+		if err != nil || zero.MatchString(UrlHintAddr) {
+			if (addr == common.Address{}) {
+				err = fmt.Errorf("UrlHint address not found and sender for creation not given")
+				return
+			}
+			txhash, err = self.backend.Transact(addr.Hex(), "", "", "", "210000", "", UrlHintCode)
+			if err != nil {
+				err = fmt.Errorf("UrlHint address not found and sender for creation failed: %v", err)
+			}
+			glog.V(logger.Detail).Infof("created UrlHint @ txhash %v\n", txhash)
+		} else {
+			glog.V(logger.Detail).Infof("UrlHint found @ %v\n", HashRegAddr)
+			return
+		}
+	}
+
+	return
+}
+
+// ReserveName(from, name) reserves name for the sender address in the globalRegistrar
+// the tx needs to be mined to take effect
+func (self *Registrar) ReserveName(address common.Address, name string) (txh string, err error) {
+	nameHex, extra := encodeName(name, 2)
+	abi := reserveAbi + nameHex + extra
+	glog.V(logger.Detail).Infof("Reserve data: %s", abi)
+	return self.backend.Transact(
+		address.Hex(),
+		GlobalRegistrarAddr,
+		"", "", "", "",
+		abi,
+	)
+}
+
+// SetAddressToName(from, name, addr) will set the Address to address for name
+// in the globalRegistrar using from as the sender of the transaction
+// the tx needs to be mined to take effect
+func (self *Registrar) SetAddressToName(from common.Address, name string, address common.Address) (txh string, err error) {
+	nameHex, extra := encodeName(name, 6)
+	addrHex := encodeAddress(address)
+
+	abi := registerAbi + nameHex + addrHex + trueHex + extra
+	glog.V(logger.Detail).Infof("SetAddressToName data: %s to %s ", abi, GlobalRegistrarAddr)
+
+	return self.backend.Transact(
+		from.Hex(),
+		GlobalRegistrarAddr,
+		"", "", "", "",
+		abi,
+	)
+}
+
+// NameToAddr(from, name) queries the registrar for the address on name
+func (self *Registrar) NameToAddr(from common.Address, name string) (address common.Address, err error) {
+	nameHex, extra := encodeName(name, 2)
+	abi := resolveAbi + nameHex + extra
+	glog.V(logger.Detail).Infof("NameToAddr data: %s", abi)
+	res, _, err := self.backend.Call(
+		from.Hex(),
+		GlobalRegistrarAddr,
+		"", "", "",
+		abi,
+	)
+	if err != nil {
+		return
+	}
+	address = common.HexToAddress(res)
+	return
+}
+
+// called as first step in the registration process on HashReg
+func (self *Registrar) SetOwner(address common.Address) (txh string, err error) {
+	return self.backend.Transact(
+		address.Hex(),
+		HashRegAddr,
+		"", "", "", "",
+		setOwnerAbi,
+	)
+}
+
+// registers some content hash to a key/code hash
+// e.g., the contract Info combined Json Doc's ContentHash
+// to CodeHash of a contract or hash of a domain
+func (self *Registrar) SetHashToHash(address common.Address, codehash, dochash common.Hash) (txh string, err error) {
+	_, err = self.SetOwner(address)
+	if err != nil {
+		return
+	}
+	codehex := common.Bytes2Hex(codehash[:])
+	dochex := common.Bytes2Hex(dochash[:])
+
+	data := registerContentHashAbi + codehex + dochex
+	glog.V(logger.Detail).Infof("SetHashToHash data: %s sent  to %v\n", data, HashRegAddr)
+	return self.backend.Transact(
+		address.Hex(),
+		HashRegAddr,
+		"", "", "", "",
+		data,
+	)
+}
+
+// SetUrlToHash(from, hash, url) registers a url to a content hash so that the content can be fetched
+// address is used as sender for the transaction and will be the owner of a new
+// registry entry on first time use
+// FIXME: silently doing nothing if sender is not the owner
+// note that with content addressed storage, this step is no longer necessary
+func (self *Registrar) SetUrlToHash(address common.Address, hash common.Hash, url string) (txh string, err error) {
+	hashHex := common.Bytes2Hex(hash[:])
+	var urlHex string
+	urlb := []byte(url)
+	var cnt byte
+	n := len(urlb)
+
+	for n > 0 {
+		if n > 32 {
+			n = 32
+		}
+		urlHex = common.Bytes2Hex(urlb[:n])
+		urlb = urlb[n:]
+		n = len(urlb)
+		bcnt := make([]byte, 32)
+		bcnt[31] = cnt
+		data := registerUrlAbi +
+			hashHex +
+			common.Bytes2Hex(bcnt) +
+			common.Bytes2Hex(common.Hex2BytesFixed(urlHex, 32))
+		txh, err = self.backend.Transact(
+			address.Hex(),
+			UrlHintAddr,
+			"", "", "", "",
+			data,
+		)
+		if err != nil {
+			return
+		}
+		cnt++
+	}
+	return
+}
+
+// HashToHash(key) resolves contenthash for key (a hash) using HashReg
+// resolution is costless non-transactional
+// implemented as direct retrieval from  db
+func (self *Registrar) HashToHash(khash common.Hash) (chash common.Hash, err error) {
+	// look up in hashReg
+	at := HashRegAddr[2:]
+	key := storageAddress(storageMapping(storageIdx2Addr(1), khash[:]))
+	hash := self.backend.StorageAt(at, key)
+
+	if hash == "0x0" || len(hash) < 3 || (hash == common.Hash{}.Hex()) {
+		err = fmt.Errorf("content hash not found for '%v'", khash.Hex())
+		return
+	}
+	copy(chash[:], common.Hex2BytesFixed(hash[2:], 32))
+	return
+}
+
+// HashToUrl(contenthash) resolves the url for contenthash using UrlHint
+// resolution is costless non-transactional
+// implemented as direct retrieval from  db
+// if we use content addressed storage, this step is no longer necessary
+func (self *Registrar) HashToUrl(chash common.Hash) (uri string, err error) {
+	// look up in URL reg
+	var str string = " "
+	var idx uint32
+	for len(str) > 0 {
+		mapaddr := storageMapping(storageIdx2Addr(1), chash[:])
+		key := storageAddress(storageFixedArray(mapaddr, storageIdx2Addr(idx)))
+		hex := self.backend.StorageAt(UrlHintAddr[2:], key)
+		str = string(common.Hex2Bytes(hex[2:]))
+		l := 0
+		for (l < len(str)) && (str[l] == 0) {
+			l++
+		}
+
+		str = str[l:]
+		uri = uri + str
+		idx++
+	}
+
+	if len(uri) == 0 {
+		err = fmt.Errorf("GetURLhint: URL hint not found for '%v'", chash.Hex())
+	}
+	return
+}
+
+func storageIdx2Addr(varidx uint32) []byte {
+	data := make([]byte, 32)
+	binary.BigEndian.PutUint32(data[28:32], varidx)
+	return data
+}
+
+func storageMapping(addr, key []byte) []byte {
+	data := make([]byte, 64)
+	copy(data[0:32], key[0:32])
+	copy(data[32:64], addr[0:32])
+	sha := crypto.Sha3(data)
+	return sha
+}
+
+func storageFixedArray(addr, idx []byte) []byte {
+	var carry byte
+	for i := 31; i >= 0; i-- {
+		var b byte = addr[i] + idx[i] + carry
+		if b < addr[i] {
+			carry = 1
+		} else {
+			carry = 0
+		}
+		addr[i] = b
+	}
+	return addr
+}
+
+func storageAddress(addr []byte) string {
+	return common.ToHex(addr)
+}
+
+func encodeAddress(address common.Address) string {
+	return addressAbiPrefix + address.Hex()[2:]
+}
+
+func encodeName(name string, index uint8) (string, string) {
+	extra := common.Bytes2Hex([]byte(name))
+	if len(name) > 32 {
+		return fmt.Sprintf("%064x", index), extra
+	}
+	return extra + falseHex[len(extra):], ""
+}
diff --git a/common/resolver/resolver_test.go b/common/registrar/registrar_test.go
similarity index 61%
rename from common/resolver/resolver_test.go
rename to common/registrar/registrar_test.go
index 02d12592e56d80a59da08d1e4bf0cd950bb485f6..7561e424e2542433d8eb49b8177ac5a7d3f007e6 100644
--- a/common/resolver/resolver_test.go
+++ b/common/registrar/registrar_test.go
@@ -1,4 +1,4 @@
-package resolver
+package registrar
 
 import (
 	"testing"
@@ -20,22 +20,22 @@ var (
 )
 
 func NewTestBackend() *testBackend {
-	HashRegContractAddress = common.BigToAddress(common.Big0).Hex()[2:]
-	UrlHintContractAddress = common.BigToAddress(common.Big1).Hex()[2:]
+	HashRegAddr = common.BigToAddress(common.Big0).Hex() //[2:]
+	UrlHintAddr = common.BigToAddress(common.Big1).Hex() //[2:]
 	self := &testBackend{}
 	self.contracts = make(map[string](map[string]string))
 
-	self.contracts[HashRegContractAddress] = make(map[string]string)
+	self.contracts[HashRegAddr[2:]] = make(map[string]string)
 	key := storageAddress(storageMapping(storageIdx2Addr(1), codehash[:]))
-	self.contracts[HashRegContractAddress][key] = hash.Hex()
+	self.contracts[HashRegAddr[2:]][key] = hash.Hex()
 
-	self.contracts[UrlHintContractAddress] = make(map[string]string)
+	self.contracts[UrlHintAddr[2:]] = make(map[string]string)
 	mapaddr := storageMapping(storageIdx2Addr(1), hash[:])
 
 	key = storageAddress(storageFixedArray(mapaddr, storageIdx2Addr(0)))
-	self.contracts[UrlHintContractAddress][key] = common.ToHex([]byte(url))
+	self.contracts[UrlHintAddr[2:]][key] = common.ToHex([]byte(url))
 	key = storageAddress(storageFixedArray(mapaddr, storageIdx2Addr(1)))
-	self.contracts[UrlHintContractAddress][key] = "0x00"
+	self.contracts[UrlHintAddr[2:]][key] = "0x0"
 	return self
 }
 
@@ -52,42 +52,45 @@ func (self *testBackend) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, ga
 	return "", nil
 }
 
-func TestKeyToContentHash(t *testing.T) {
+func (self *testBackend) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, string, error) {
+	return "", "", nil
+}
+
+func TestSetGlobalRegistrar(t *testing.T) {
 	b := NewTestBackend()
 	res := New(b)
-
-	got, err := res.KeyToContentHash(codehash)
+	_, err := res.SetGlobalRegistrar("addresshex", common.BigToAddress(common.Big1))
 	if err != nil {
-		t.Errorf("expected no error, got %v", err)
-	} else {
-		if got != hash {
-			t.Errorf("incorrect result, expected '%v', got '%v'", hash.Hex(), got.Hex())
-		}
+		t.Errorf("unexpected error: %v'", err)
 	}
 }
 
-func TestContentHashToUrl(t *testing.T) {
+func TestHashToHash(t *testing.T) {
 	b := NewTestBackend()
 	res := New(b)
-	got, err := res.ContentHashToUrl(hash)
+	// res.SetHashReg()
+
+	got, err := res.HashToHash(codehash)
 	if err != nil {
 		t.Errorf("expected no error, got %v", err)
 	} else {
-		if got != url {
-			t.Errorf("incorrect result, expected '%v', got '%s'", url, got)
+		if got != hash {
+			t.Errorf("incorrect result, expected '%v', got '%v'", hash.Hex(), got.Hex())
 		}
 	}
 }
 
-func TestKeyToUrl(t *testing.T) {
+func TestHashToUrl(t *testing.T) {
 	b := NewTestBackend()
 	res := New(b)
-	got, _, err := res.KeyToUrl(codehash)
+	// res.SetUrlHint()
+
+	got, err := res.HashToUrl(hash)
 	if err != nil {
-		t.Errorf("expected no error, got %v", err)
+		t.Errorf("expected 	 error, got %v", err)
 	} else {
 		if got != url {
-			t.Errorf("incorrect result, expected \n'%s', got \n'%s'", url, got)
+			t.Errorf("incorrect result, expected '%v', got '%s'", url, got)
 		}
 	}
 }
diff --git a/common/resolver/contracts.go b/common/resolver/contracts.go
deleted file mode 100644
index 4aad95e43636038416df61426885be1d8d4ee1e4..0000000000000000000000000000000000000000
--- a/common/resolver/contracts.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package resolver
-
-const ( // built-in contracts address and code
-	ContractCodeURLhint = "0x60c180600c6000396000f30060003560e060020a90048063300a3bbf14601557005b6024600435602435604435602a565b60006000f35b6000600084815260200190815260200160002054600160a060020a0316600014806078575033600160a060020a03166000600085815260200190815260200160002054600160a060020a0316145b607f5760bc565b336000600085815260200190815260200160002081905550806001600085815260200190815260200160002083610100811060b657005b01819055505b50505056"
-	/*
-		contract URLhint {
-			function register(uint256 _hash, uint8 idx, uint256 _url) {
-				if (owner[_hash] == 0 || owner[_hash] == msg.sender) {
-					owner[_hash] = msg.sender;
-					url[_hash][idx] = _url;
-				}
-			}
-			mapping (uint256 => address) owner;
-			mapping (uint256 => uint256[256]) url;
-		}
-	*/
-
-	ContractCodeHashReg = "0x609880600c6000396000f30060003560e060020a9004806331e12c2014601f578063d66d6c1014602b57005b6025603d565b60006000f35b6037600435602435605d565b60006000f35b600054600160a060020a0316600014605357605b565b336000819055505b565b600054600160a060020a031633600160a060020a031614607b576094565b8060016000848152602001908152602001600020819055505b505056"
-	/*
-		   contract HashReg {
-			function setowner() {
-				if (owner == 0) {
-					owner = msg.sender;
-				}
-			}
-		   	function register(uint256 _key, uint256 _content) {
-				if (msg.sender == owner) {
-		   			content[_key] = _content;
-				}
-		   	}
-			address owner;
-		   	mapping (uint256 => uint256) content;
-		   }
-	*/
-
-)
diff --git a/common/resolver/resolver.go b/common/resolver/resolver.go
deleted file mode 100644
index 9016547e10cec644e11199f765c753ff8ffeaaf1..0000000000000000000000000000000000000000
--- a/common/resolver/resolver.go
+++ /dev/null
@@ -1,232 +0,0 @@
-package resolver
-
-import (
-	"encoding/binary"
-	"fmt"
-
-	"github.com/ethereum/go-ethereum/common"
-	"github.com/ethereum/go-ethereum/crypto"
-	"github.com/ethereum/go-ethereum/logger"
-	"github.com/ethereum/go-ethereum/logger/glog"
-)
-
-/*
-Resolver implements the Ethereum DNS mapping
-HashReg : Key Hash (hash of domain name or contract code) -> Content Hash
-UrlHint : Content Hash -> Url Hint
-
-The resolver is meant to be called by the roundtripper transport implementation
-of a url scheme
-*/
-
-// // contract addresses will be hardcoded after they're created
-var UrlHintContractAddress, HashRegContractAddress string
-
-const (
-	txValue    = "0"
-	txGas      = "100000"
-	txGasPrice = "1000000000000"
-)
-
-func abi(s string) string {
-	return common.ToHex(crypto.Sha3([]byte(s))[:4])
-}
-
-var (
-	registerContentHashAbi = abi("register(uint256,uint256)")
-	registerUrlAbi         = abi("register(uint256,uint8,uint256)")
-	setOwnerAbi            = abi("setowner()")
-)
-
-type Backend interface {
-	StorageAt(string, string) string
-	Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error)
-}
-
-type Resolver struct {
-	backend Backend
-}
-
-func New(eth Backend) *Resolver {
-	return &Resolver{eth}
-}
-
-// for testing and play temporarily
-// ideally the HashReg and UrlHint contracts should be in the genesis block
-// if we got build-in support for natspec/contract info
-// there should be only one of these officially endorsed
-// addresses as constants
-// TODO: could get around this with namereg, check
-func (self *Resolver) CreateContracts(addr common.Address) (err error) {
-	HashRegContractAddress, err = self.backend.Transact(addr.Hex(), "", "", txValue, txGas, txGasPrice, ContractCodeHashReg)
-	if err != nil {
-		return
-	}
-	UrlHintContractAddress, err = self.backend.Transact(addr.Hex(), "", "", txValue, txGas, txGasPrice, ContractCodeURLhint)
-	glog.V(logger.Detail).Infof("HashReg @ %v\nUrlHint @ %v\n", HashRegContractAddress, UrlHintContractAddress)
-	return
-}
-
-// called as first step in the registration process on HashReg
-func (self *Resolver) SetOwner(address common.Address) (txh string, err error) {
-	return self.backend.Transact(
-		address.Hex(),
-		HashRegContractAddress,
-		"", txValue, txGas, txGasPrice,
-		setOwnerAbi,
-	)
-}
-
-// registers some content hash to a key/code hash
-// e.g., the contract Info combined Json Doc's ContentHash
-// to CodeHash of a contract or hash of a domain
-// kept
-func (self *Resolver) RegisterContentHash(address common.Address, codehash, dochash common.Hash) (txh string, err error) {
-	_, err = self.SetOwner(address)
-	if err != nil {
-		return
-	}
-	codehex := common.Bytes2Hex(codehash[:])
-	dochex := common.Bytes2Hex(dochash[:])
-
-	data := registerContentHashAbi + codehex + dochex
-	return self.backend.Transact(
-		address.Hex(),
-		HashRegContractAddress,
-		"", txValue, txGas, txGasPrice,
-		data,
-	)
-}
-
-// registers a url to a content hash so that the content can be fetched
-// address is used as sender for the transaction and will be the owner of a new
-// registry entry on first time use
-// FIXME: silently doing nothing if sender is not the owner
-// note that with content addressed storage, this step is no longer necessary
-// it could be purely
-func (self *Resolver) RegisterUrl(address common.Address, hash common.Hash, url string) (txh string, err error) {
-	hashHex := common.Bytes2Hex(hash[:])
-	var urlHex string
-	urlb := []byte(url)
-	var cnt byte
-	n := len(urlb)
-
-	for n > 0 {
-		if n > 32 {
-			n = 32
-		}
-		urlHex = common.Bytes2Hex(urlb[:n])
-		urlb = urlb[n:]
-		n = len(urlb)
-		bcnt := make([]byte, 32)
-		bcnt[31] = cnt
-		data := registerUrlAbi +
-			hashHex +
-			common.Bytes2Hex(bcnt) +
-			common.Bytes2Hex(common.Hex2BytesFixed(urlHex, 32))
-		txh, err = self.backend.Transact(
-			address.Hex(),
-			UrlHintContractAddress,
-			"", txValue, txGas, txGasPrice,
-			data,
-		)
-		if err != nil {
-			return
-		}
-		cnt++
-	}
-	return
-}
-
-func (self *Resolver) Register(address common.Address, codehash, dochash common.Hash, url string) (txh string, err error) {
-
-	_, err = self.RegisterContentHash(address, codehash, dochash)
-	if err != nil {
-		return
-	}
-	return self.RegisterUrl(address, dochash, url)
-}
-
-// resolution is costless non-transactional
-// implemented as direct retrieval from  db
-func (self *Resolver) KeyToContentHash(khash common.Hash) (chash common.Hash, err error) {
-	// look up in hashReg
-	at := common.Bytes2Hex(common.FromHex(HashRegContractAddress))
-	key := storageAddress(storageMapping(storageIdx2Addr(1), khash[:]))
-	hash := self.backend.StorageAt(at, key)
-
-	if hash == "0x0" || len(hash) < 3 {
-		err = fmt.Errorf("content hash not found for '%v'", khash.Hex())
-		return
-	}
-	copy(chash[:], common.Hex2BytesFixed(hash[2:], 32))
-	return
-}
-
-// retrieves the url-hint for the content hash -
-// if we use content addressed storage, this step is no longer necessary
-func (self *Resolver) ContentHashToUrl(chash common.Hash) (uri string, err error) {
-	// look up in URL reg
-	var str string = " "
-	var idx uint32
-	for len(str) > 0 {
-		mapaddr := storageMapping(storageIdx2Addr(1), chash[:])
-		key := storageAddress(storageFixedArray(mapaddr, storageIdx2Addr(idx)))
-		hex := self.backend.StorageAt(UrlHintContractAddress, key)
-		str = string(common.Hex2Bytes(hex[2:]))
-		l := len(str)
-		for (l > 0) && (str[l-1] == 0) {
-			l--
-		}
-		str = str[:l]
-		uri = uri + str
-		idx++
-	}
-
-	if len(uri) == 0 {
-		err = fmt.Errorf("GetURLhint: URL hint not found for '%v'", chash.Hex())
-	}
-	return
-}
-
-func (self *Resolver) KeyToUrl(key common.Hash) (uri string, hash common.Hash, err error) {
-	// look up in urlHint
-	hash, err = self.KeyToContentHash(key)
-	if err != nil {
-		return
-	}
-	uri, err = self.ContentHashToUrl(hash)
-	return
-}
-
-func storageIdx2Addr(varidx uint32) []byte {
-	data := make([]byte, 32)
-	binary.BigEndian.PutUint32(data[28:32], varidx)
-	return data
-}
-
-func storageMapping(addr, key []byte) []byte {
-	data := make([]byte, 64)
-	copy(data[0:32], key[0:32])
-	copy(data[32:64], addr[0:32])
-	sha := crypto.Sha3(data)
-	return sha
-}
-
-func storageFixedArray(addr, idx []byte) []byte {
-	var carry byte
-	for i := 31; i >= 0; i-- {
-		var b byte = addr[i] + idx[i] + carry
-		if b < addr[i] {
-			carry = 1
-		} else {
-			carry = 0
-		}
-		addr[i] = b
-	}
-	return addr
-}
-
-func storageAddress(addr []byte) string {
-	return common.ToHex(addr)
-}
diff --git a/eth/backend.go b/eth/backend.go
index e62252b6cd0809149d915c5010c5e01e10e34ada..38e06bcf81eb92b4d5ee43b848814cb776f7b9c7 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -70,6 +70,7 @@ type Config struct {
 	VmDebug   bool
 	NatSpec   bool
 	AutoDAG   bool
+	PowTest   bool
 
 	MaxPeers        int
 	MaxPendingPeers int
@@ -221,6 +222,7 @@ type Ethereum struct {
 	NatSpec       bool
 	DataDir       string
 	AutoDAG       bool
+	PowTest       bool
 	autodagquit   chan bool
 	etherbase     common.Address
 	clientVersion string
@@ -329,6 +331,7 @@ func New(config *Config) (*Ethereum, error) {
 		MinerThreads:            config.MinerThreads,
 		SolcPath:                config.SolcPath,
 		AutoDAG:                 config.AutoDAG,
+		PowTest:                 config.PowTest,
 		GpoMinGasPrice:          config.GpoMinGasPrice,
 		GpoMaxGasPrice:          config.GpoMaxGasPrice,
 		GpoFullBlockRatio:       config.GpoFullBlockRatio,
@@ -337,7 +340,15 @@ func New(config *Config) (*Ethereum, error) {
 		GpobaseCorrectionFactor: config.GpobaseCorrectionFactor,
 	}
 
-	eth.pow = ethash.New()
+	if config.PowTest {
+		glog.V(logger.Info).Infof("ethash used in test mode")
+		eth.pow, err = ethash.NewForTesting()
+		if err != nil {
+			return nil, err
+		}
+	} else {
+		eth.pow = ethash.New()
+	}
 	genesis := core.GenesisBlock(uint64(config.GenesisNonce), stateDb)
 	eth.chainManager, err = core.NewChainManager(genesis, blockDb, stateDb, extraDb, eth.pow, eth.EventMux())
 	if err != nil {
diff --git a/jsre/pp_js.go b/jsre/pp_js.go
index 20821e4a1bdcf0a65f15e7e13edc36572c2bb83f..735132bb741ce30696f492ccab82ea09212c1c05 100644
--- a/jsre/pp_js.go
+++ b/jsre/pp_js.go
@@ -97,7 +97,15 @@ var isMemberFunction = function(object, member) {
 }
 
 var isBigNumber = function (object) {
-    return typeof BigNumber !== 'undefined' && object instanceof BigNumber;
+    var result = typeof BigNumber !== 'undefined' && object instanceof BigNumber;
+
+    if (!result) {
+    	if(typeof(object) === "object") {
+			result = object.constructor.toString().indexOf("function BigNumber(") == 0;
+		}
+    }
+
+    return result
 };
 
 function prettyPrint(/* */) {
diff --git a/rpc/api/admin.go b/rpc/api/admin.go
index b27482cfea5166e7d81e086942b67c526ad9aec7..c5f0260906daee646f6cad86a76b2f282e92bf4f 100644
--- a/rpc/api/admin.go
+++ b/rpc/api/admin.go
@@ -3,10 +3,18 @@ package api
 import (
 	"fmt"
 	"io"
+	"math/big"
 	"os"
+	"time"
 
+	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/common/compiler"
+	"github.com/ethereum/go-ethereum/common/docserver"
+	"github.com/ethereum/go-ethereum/common/natspec"
+	"github.com/ethereum/go-ethereum/common/registrar"
 	"github.com/ethereum/go-ethereum/core"
 	"github.com/ethereum/go-ethereum/core/types"
+	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/eth"
 	"github.com/ethereum/go-ethereum/logger/glog"
 	"github.com/ethereum/go-ethereum/rlp"
@@ -24,17 +32,29 @@ const (
 var (
 	// mapping between methods and handlers
 	AdminMapping = map[string]adminhandler{
-		"admin_addPeer":         (*adminApi).AddPeer,
-		"admin_peers":           (*adminApi).Peers,
-		"admin_nodeInfo":        (*adminApi).NodeInfo,
-		"admin_exportChain":     (*adminApi).ExportChain,
-		"admin_importChain":     (*adminApi).ImportChain,
-		"admin_verbosity":       (*adminApi).Verbosity,
-		"admin_chainSyncStatus": (*adminApi).ChainSyncStatus,
-		"admin_setSolc":         (*adminApi).SetSolc,
-		"admin_datadir":         (*adminApi).DataDir,
-		"admin_startRPC":        (*adminApi).StartRPC,
-		"admin_stopRPC":         (*adminApi).StopRPC,
+		"admin_addPeer":            (*adminApi).AddPeer,
+		"admin_peers":              (*adminApi).Peers,
+		"admin_nodeInfo":           (*adminApi).NodeInfo,
+		"admin_exportChain":        (*adminApi).ExportChain,
+		"admin_importChain":        (*adminApi).ImportChain,
+		"admin_verbosity":          (*adminApi).Verbosity,
+		"admin_chainSyncStatus":    (*adminApi).ChainSyncStatus,
+		"admin_setSolc":            (*adminApi).SetSolc,
+		"admin_datadir":            (*adminApi).DataDir,
+		"admin_startRPC":           (*adminApi).StartRPC,
+		"admin_stopRPC":            (*adminApi).StopRPC,
+		"admin_setGlobalRegistrar": (*adminApi).SetGlobalRegistrar,
+		"admin_setHashReg":         (*adminApi).SetHashReg,
+		"admin_setUrlHint":         (*adminApi).SetUrlHint,
+		"admin_saveInfo":           (*adminApi).SaveInfo,
+		"admin_register":           (*adminApi).Register,
+		"admin_registerUrl":        (*adminApi).RegisterUrl,
+		"admin_startNatSpec":       (*adminApi).StartNatSpec,
+		"admin_stopNatSpec":        (*adminApi).StopNatSpec,
+		"admin_getContractInfo":    (*adminApi).GetContractInfo,
+		"admin_httpGet":            (*adminApi).HttpGet,
+		"admin_sleepBlocks":        (*adminApi).SleepBlocks,
+		"admin_sleep":              (*adminApi).Sleep,
 	}
 )
 
@@ -47,6 +67,7 @@ type adminApi struct {
 	ethereum *eth.Ethereum
 	codec    codec.Codec
 	coder    codec.ApiCoder
+	ds       *docserver.DocServer
 }
 
 // create a new admin api instance
@@ -56,6 +77,7 @@ func NewAdminApi(xeth *xeth.XEth, ethereum *eth.Ethereum, codec codec.Codec) *ad
 		ethereum: ethereum,
 		codec:    codec,
 		coder:    codec.New(nil),
+		ds:       docserver.New("/"),
 	}
 }
 
@@ -244,3 +266,195 @@ func (self *adminApi) StopRPC(req *shared.Request) (interface{}, error) {
 	comms.StopHttp()
 	return true, nil
 }
+
+func (self *adminApi) SleepBlocks(req *shared.Request) (interface{}, error) {
+	args := new(SleepBlocksArgs)
+	if err := self.coder.Decode(req.Params, &args); err != nil {
+		return nil, shared.NewDecodeParamError(err.Error())
+	}
+	var timer <-chan time.Time
+	var height *big.Int
+	var err error
+	if args.Timeout > 0 {
+		timer = time.NewTimer(time.Duration(args.Timeout) * time.Second).C
+	}
+
+	height = new(big.Int).Add(self.xeth.CurrentBlock().Number(), big.NewInt(args.N))
+	height, err = sleepBlocks(self.xeth.UpdateState(), height, timer)
+	if err != nil {
+		return nil, err
+	}
+	return height.Uint64(), nil
+}
+
+func sleepBlocks(wait chan *big.Int, height *big.Int, timer <-chan time.Time) (newHeight *big.Int, err error) {
+	wait <- height
+	select {
+	case <-timer:
+		// if times out make sure the xeth loop does not block
+		go func() {
+			select {
+			case wait <- nil:
+			case <-wait:
+			}
+		}()
+		return nil, fmt.Errorf("timeout")
+	case newHeight = <-wait:
+	}
+	return
+}
+
+func (self *adminApi) Sleep(req *shared.Request) (interface{}, error) {
+	args := new(SleepArgs)
+	if err := self.coder.Decode(req.Params, &args); err != nil {
+		return nil, shared.NewDecodeParamError(err.Error())
+	}
+	time.Sleep(time.Duration(args.S) * time.Second)
+	return nil, nil
+}
+
+func (self *adminApi) SetGlobalRegistrar(req *shared.Request) (interface{}, error) {
+	args := new(SetGlobalRegistrarArgs)
+	if err := self.coder.Decode(req.Params, &args); err != nil {
+		return nil, shared.NewDecodeParamError(err.Error())
+	}
+
+	sender := common.HexToAddress(args.ContractAddress)
+
+	reg := registrar.New(self.xeth)
+	txhash, err := reg.SetGlobalRegistrar(args.NameReg, sender)
+	if err != nil {
+		return false, err
+	}
+
+	return txhash, nil
+}
+
+func (self *adminApi) SetHashReg(req *shared.Request) (interface{}, error) {
+	args := new(SetHashRegArgs)
+	if err := self.coder.Decode(req.Params, &args); err != nil {
+		return nil, shared.NewDecodeParamError(err.Error())
+	}
+
+	reg := registrar.New(self.xeth)
+	sender := common.HexToAddress(args.Sender)
+	txhash, err := reg.SetHashReg(args.HashReg, sender)
+	if err != nil {
+		return false, err
+	}
+
+	return txhash, nil
+}
+
+func (self *adminApi) SetUrlHint(req *shared.Request) (interface{}, error) {
+	args := new(SetUrlHintArgs)
+	if err := self.coder.Decode(req.Params, &args); err != nil {
+		return nil, shared.NewDecodeParamError(err.Error())
+	}
+
+	urlHint := args.UrlHint
+	sender := common.HexToAddress(args.Sender)
+
+	reg := registrar.New(self.xeth)
+	txhash, err := reg.SetUrlHint(urlHint, sender)
+	if err != nil {
+		return nil, err
+	}
+
+	return txhash, nil
+}
+
+func (self *adminApi) SaveInfo(req *shared.Request) (interface{}, error) {
+	args := new(SaveInfoArgs)
+	if err := self.coder.Decode(req.Params, &args); err != nil {
+		return nil, shared.NewDecodeParamError(err.Error())
+	}
+
+	contenthash, err := compiler.SaveInfo(&args.ContractInfo, args.Filename)
+	if err != nil {
+		return nil, err
+	}
+
+	return contenthash.Hex(), nil
+}
+
+func (self *adminApi) Register(req *shared.Request) (interface{}, error) {
+	args := new(RegisterArgs)
+	if err := self.coder.Decode(req.Params, &args); err != nil {
+		return nil, shared.NewDecodeParamError(err.Error())
+	}
+
+	sender := common.HexToAddress(args.Sender)
+	// sender and contract address are passed as hex strings
+	codeb := self.xeth.CodeAtBytes(args.Address)
+	codeHash := common.BytesToHash(crypto.Sha3(codeb))
+	contentHash := common.HexToHash(args.ContentHashHex)
+	registry := registrar.New(self.xeth)
+
+	_, err := registry.SetHashToHash(sender, codeHash, contentHash)
+	if err != nil {
+		return false, err
+	}
+
+	return true, nil
+}
+
+func (self *adminApi) RegisterUrl(req *shared.Request) (interface{}, error) {
+	args := new(RegisterUrlArgs)
+	if err := self.coder.Decode(req.Params, &args); err != nil {
+		return nil, shared.NewDecodeParamError(err.Error())
+	}
+
+	sender := common.HexToAddress(args.Sender)
+	registry := registrar.New(self.xeth)
+	_, err := registry.SetUrlToHash(sender, common.HexToHash(args.ContentHash), args.Url)
+	if err != nil {
+		return false, err
+	}
+
+	return true, nil
+}
+
+func (self *adminApi) StartNatSpec(req *shared.Request) (interface{}, error) {
+	self.ethereum.NatSpec = true
+	return true, nil
+}
+
+func (self *adminApi) StopNatSpec(req *shared.Request) (interface{}, error) {
+	self.ethereum.NatSpec = false
+	return true, nil
+}
+
+func (self *adminApi) GetContractInfo(req *shared.Request) (interface{}, error) {
+	args := new(GetContractInfoArgs)
+	if err := self.coder.Decode(req.Params, &args); err != nil {
+		return nil, shared.NewDecodeParamError(err.Error())
+	}
+
+	infoDoc, err := natspec.FetchDocsForContract(args.Contract, self.xeth, self.ds)
+	if err != nil {
+		return nil, err
+	}
+
+	var info interface{}
+	err = self.coder.Decode(infoDoc, &info)
+	if err != nil {
+		return nil, err
+	}
+
+	return info, nil
+}
+
+func (self *adminApi) HttpGet(req *shared.Request) (interface{}, error) {
+	args := new(HttpGetArgs)
+	if err := self.coder.Decode(req.Params, &args); err != nil {
+		return nil, shared.NewDecodeParamError(err.Error())
+	}
+
+	resp, err := self.ds.Get(args.Uri, args.Path)
+	if err != nil {
+		return nil, err
+	}
+
+	return string(resp), nil
+}
diff --git a/rpc/api/admin_args.go b/rpc/api/admin_args.go
index 5437971caa04c357d0e15fab9bf15d6c3349bd75..532907905612b8e9fed1df6d8405932ff5aaf33d 100644
--- a/rpc/api/admin_args.go
+++ b/rpc/api/admin_args.go
@@ -3,6 +3,7 @@ package api
 import (
 	"encoding/json"
 
+	"github.com/ethereum/go-ethereum/common/compiler"
 	"github.com/ethereum/go-ethereum/rpc/shared"
 )
 
@@ -113,7 +114,7 @@ func (args *StartRPCArgs) UnmarshalJSON(b []byte) (err error) {
 	args.ListenPort = 8545
 	args.Apis = "net,eth,web3"
 
-	if len(obj) >= 1 {
+	if len(obj) >= 1 && obj[0] != nil {
 		if addr, ok := obj[0].(string); ok {
 			args.ListenAddress = addr
 		} else {
@@ -121,7 +122,7 @@ func (args *StartRPCArgs) UnmarshalJSON(b []byte) (err error) {
 		}
 	}
 
-	if len(obj) >= 2 {
+	if len(obj) >= 2 && obj[1] != nil {
 		if port, ok := obj[1].(float64); ok && port >= 0 && port <= 64*1024 {
 			args.ListenPort = uint(port)
 		} else {
@@ -129,7 +130,7 @@ func (args *StartRPCArgs) UnmarshalJSON(b []byte) (err error) {
 		}
 	}
 
-	if len(obj) >= 3 {
+	if len(obj) >= 3 && obj[2] != nil {
 		if corsDomain, ok := obj[2].(string); ok {
 			args.CorsDomain = corsDomain
 		} else {
@@ -137,7 +138,7 @@ func (args *StartRPCArgs) UnmarshalJSON(b []byte) (err error) {
 		}
 	}
 
-	if len(obj) >= 4 {
+	if len(obj) >= 4 && obj[3] != nil {
 		if apis, ok := obj[3].(string); ok {
 			args.Apis = apis
 		} else {
@@ -147,3 +148,327 @@ func (args *StartRPCArgs) UnmarshalJSON(b []byte) (err error) {
 
 	return nil
 }
+
+type SleepArgs struct {
+	S int
+}
+
+func (args *SleepArgs) UnmarshalJSON(b []byte) (err error) {
+
+	var obj []interface{}
+	if err := json.Unmarshal(b, &obj); err != nil {
+		return shared.NewDecodeParamError(err.Error())
+	}
+	if len(obj) >= 1 {
+		if obj[0] != nil {
+			if n, err := numString(obj[0]); err == nil {
+				args.S = int(n.Int64())
+			} else {
+				return shared.NewInvalidTypeError("N", "not an integer: "+err.Error())
+			}
+		} else {
+			return shared.NewInsufficientParamsError(0, 1)
+		}
+	}
+	return nil
+}
+
+type SleepBlocksArgs struct {
+	N       int64
+	Timeout int64
+}
+
+func (args *SleepBlocksArgs) UnmarshalJSON(b []byte) (err error) {
+
+	var obj []interface{}
+	if err := json.Unmarshal(b, &obj); err != nil {
+		return shared.NewDecodeParamError(err.Error())
+	}
+
+	args.N = 1
+	args.Timeout = 0
+	if len(obj) >= 1 && obj[0] != nil {
+		if n, err := numString(obj[0]); err == nil {
+			args.N = n.Int64()
+		} else {
+			return shared.NewInvalidTypeError("N", "not an integer: "+err.Error())
+		}
+	}
+
+	if len(obj) >= 2 && obj[1] != nil {
+		if n, err := numString(obj[1]); err == nil {
+			args.Timeout = n.Int64()
+		} else {
+			return shared.NewInvalidTypeError("Timeout", "not an integer: "+err.Error())
+		}
+	}
+
+	return nil
+}
+
+type SetGlobalRegistrarArgs struct {
+	NameReg         string
+	ContractAddress string
+}
+
+func (args *SetGlobalRegistrarArgs) UnmarshalJSON(b []byte) (err error) {
+	var obj []interface{}
+	if err := json.Unmarshal(b, &obj); err != nil {
+		return shared.NewDecodeParamError(err.Error())
+	}
+
+	if len(obj) == 0 {
+		return shared.NewDecodeParamError("Expected namereg address")
+	}
+
+	if len(obj) >= 1 {
+		if namereg, ok := obj[0].(string); ok {
+			args.NameReg = namereg
+		} else {
+			return shared.NewInvalidTypeError("NameReg", "not a string")
+		}
+	}
+
+	if len(obj) >= 2 && obj[1] != nil {
+		if addr, ok := obj[1].(string); ok {
+			args.ContractAddress = addr
+		} else {
+			return shared.NewInvalidTypeError("ContractAddress", "not a string")
+		}
+	}
+
+	return nil
+}
+
+type SetHashRegArgs struct {
+	HashReg string
+	Sender  string
+}
+
+func (args *SetHashRegArgs) UnmarshalJSON(b []byte) (err error) {
+	var obj []interface{}
+	if err := json.Unmarshal(b, &obj); err != nil {
+		return shared.NewDecodeParamError(err.Error())
+	}
+
+	if len(obj) >= 1 && obj[0] != nil {
+		if hashreg, ok := obj[0].(string); ok {
+			args.HashReg = hashreg
+		} else {
+			return shared.NewInvalidTypeError("HashReg", "not a string")
+		}
+	}
+
+	if len(obj) >= 2 && obj[1] != nil {
+		if sender, ok := obj[1].(string); ok {
+			args.Sender = sender
+		} else {
+			return shared.NewInvalidTypeError("Sender", "not a string")
+		}
+	}
+
+	return nil
+}
+
+type SetUrlHintArgs struct {
+	UrlHint string
+	Sender  string
+}
+
+func (args *SetUrlHintArgs) UnmarshalJSON(b []byte) (err error) {
+	var obj []interface{}
+	if err := json.Unmarshal(b, &obj); err != nil {
+		return shared.NewDecodeParamError(err.Error())
+	}
+
+	if len(obj) >= 1 && obj[0] != nil {
+		if urlhint, ok := obj[0].(string); ok {
+			args.UrlHint = urlhint
+		} else {
+			return shared.NewInvalidTypeError("UrlHint", "not a string")
+		}
+	}
+
+	if len(obj) >= 2 && obj[1] != nil {
+		if sender, ok := obj[1].(string); ok {
+			args.Sender = sender
+		} else {
+			return shared.NewInvalidTypeError("Sender", "not a string")
+		}
+	}
+
+	return nil
+}
+
+type SaveInfoArgs struct {
+	ContractInfo compiler.ContractInfo
+	Filename     string
+}
+
+func (args *SaveInfoArgs) UnmarshalJSON(b []byte) (err error) {
+	var obj []interface{}
+	if err := json.Unmarshal(b, &obj); err != nil {
+		return shared.NewDecodeParamError(err.Error())
+	}
+
+	if len(obj) < 2 {
+		return shared.NewInsufficientParamsError(len(obj), 2)
+	}
+
+	if jsonraw, err := json.Marshal(obj[0]); err == nil {
+		if err = json.Unmarshal(jsonraw, &args.ContractInfo); err != nil {
+			return err
+		}
+	} else {
+		return err
+	}
+
+	if filename, ok := obj[1].(string); ok {
+		args.Filename = filename
+	} else {
+		return shared.NewInvalidTypeError("Filename", "not a string")
+	}
+
+	return nil
+}
+
+type RegisterArgs struct {
+	Sender         string
+	Address        string
+	ContentHashHex string
+}
+
+func (args *RegisterArgs) UnmarshalJSON(b []byte) (err error) {
+	var obj []interface{}
+	if err := json.Unmarshal(b, &obj); err != nil {
+		return shared.NewDecodeParamError(err.Error())
+	}
+
+	if len(obj) < 3 {
+		return shared.NewInsufficientParamsError(len(obj), 3)
+	}
+
+	if len(obj) >= 1 {
+		if sender, ok := obj[0].(string); ok {
+			args.Sender = sender
+		} else {
+			return shared.NewInvalidTypeError("Sender", "not a string")
+		}
+	}
+
+	if len(obj) >= 2 {
+		if address, ok := obj[1].(string); ok {
+			args.Address = address
+		} else {
+			return shared.NewInvalidTypeError("Address", "not a string")
+		}
+	}
+
+	if len(obj) >= 3 {
+		if hex, ok := obj[2].(string); ok {
+			args.ContentHashHex = hex
+		} else {
+			return shared.NewInvalidTypeError("ContentHashHex", "not a string")
+		}
+	}
+
+	return nil
+}
+
+type RegisterUrlArgs struct {
+	Sender      string
+	ContentHash string
+	Url         string
+}
+
+func (args *RegisterUrlArgs) UnmarshalJSON(b []byte) (err error) {
+	var obj []interface{}
+	if err := json.Unmarshal(b, &obj); err != nil {
+		return shared.NewDecodeParamError(err.Error())
+	}
+
+	if len(obj) >= 1 {
+		if sender, ok := obj[0].(string); ok {
+			args.Sender = sender
+		} else {
+			return shared.NewInvalidTypeError("Sender", "not a string")
+		}
+	}
+
+	if len(obj) >= 2 {
+		if sender, ok := obj[1].(string); ok {
+			args.ContentHash = sender
+		} else {
+			return shared.NewInvalidTypeError("ContentHash", "not a string")
+		}
+	}
+
+	if len(obj) >= 3 {
+		if sender, ok := obj[2].(string); ok {
+			args.Url = sender
+		} else {
+			return shared.NewInvalidTypeError("Url", "not a string")
+		}
+	}
+
+	return nil
+}
+
+type GetContractInfoArgs struct {
+	Contract string
+}
+
+func (args *GetContractInfoArgs) UnmarshalJSON(b []byte) (err error) {
+	var obj []interface{}
+	if err := json.Unmarshal(b, &obj); err != nil {
+		return shared.NewDecodeParamError(err.Error())
+	}
+
+	if len(obj) < 1 {
+		return shared.NewInsufficientParamsError(len(obj), 1)
+	}
+
+	if len(obj) >= 1 {
+		if contract, ok := obj[0].(string); ok {
+			args.Contract = contract
+		} else {
+			return shared.NewInvalidTypeError("Contract", "not a string")
+		}
+	}
+
+	return nil
+}
+
+type HttpGetArgs struct {
+	Uri  string
+	Path string
+}
+
+func (args *HttpGetArgs) UnmarshalJSON(b []byte) (err error) {
+	var obj []interface{}
+	if err := json.Unmarshal(b, &obj); err != nil {
+		return shared.NewDecodeParamError(err.Error())
+	}
+
+	if len(obj) < 1 {
+		return shared.NewInsufficientParamsError(len(obj), 1)
+	}
+
+	if len(obj) >= 1 {
+		if uri, ok := obj[0].(string); ok {
+			args.Uri = uri
+		} else {
+			return shared.NewInvalidTypeError("Uri", "not a string")
+		}
+	}
+
+	if len(obj) >= 2 && obj[1] != nil {
+		if path, ok := obj[1].(string); ok {
+			args.Path = path
+		} else {
+			return shared.NewInvalidTypeError("Path", "not a string")
+		}
+	}
+
+	return nil
+}
diff --git a/rpc/api/admin_js.go b/rpc/api/admin_js.go
index 97642ade71df59682915f88b5218bc4ea622f52a..ddfa2ea04f58ed66b70a78d2ce0f9c8ca7f94fd5 100644
--- a/rpc/api/admin_js.go
+++ b/rpc/api/admin_js.go
@@ -9,73 +9,128 @@ web3._extend({
 			name: 'addPeer',
 			call: 'admin_addPeer',
 			params: 1,
-			inputFormatter: [web3._extend.utils.formatInputString],
-			outputFormatter: web3._extend.formatters.formatOutputBool
+			inputFormatter: [null]
 		}),
 		new web3._extend.Method({
 			name: 'exportChain',
 			call: 'admin_exportChain',
 			params: 1,
-			inputFormatter: [web3._extend.utils.formatInputString],
-			outputFormatter: function(obj) { return obj; }
+			inputFormatter: [null]
 		}),
 		new web3._extend.Method({
 			name: 'importChain',
 			call: 'admin_importChain',
 			params: 1,
-			inputFormatter: [web3._extend.utils.formatInputString],
-			outputFormatter: function(obj) { return obj; }
+			inputFormatter: [null]
+		}),
+		new web3._extend.Method({
+			name: 'sleepBlocks',
+			call: 'admin_sleepBlocks',
+			params: 2,
+			inputFormatter: [null, null]
 		}),
 		new web3._extend.Method({
 			name: 'verbosity',
 			call: 'admin_verbosity',
 			params: 1,
-			inputFormatter: [web3._extend.utils.formatInputInt],
-			outputFormatter: web3._extend.formatters.formatOutputBool
+			inputFormatter: [web3._extend.utils.fromDecimal]
 		}),
 		new web3._extend.Method({
 			name: 'setSolc',
 			call: 'admin_setSolc',
 			params: 1,
-			inputFormatter: [web3._extend.utils.formatInputString],
-			outputFormatter: web3._extend.formatters.formatOutputString
+			inputFormatter: [null]
 		}),
 		new web3._extend.Method({
 			name: 'startRPC',
 			call: 'admin_startRPC',
 			params: 4,
-			inputFormatter: [web3._extend.utils.formatInputString,web3._extend.utils.formatInputInteger,web3._extend.utils.formatInputString,web3._extend.utils.formatInputString],
-			outputFormatter: web3._extend.formatters.formatOutputBool
+			inputFormatter: [null, null, null, null]
 		}),
 		new web3._extend.Method({
 			name: 'stopRPC',
 			call: 'admin_stopRPC',
 			params: 0,
-			inputFormatter: [],
-			outputFormatter: web3._extend.formatters.formatOutputBool
+			inputFormatter: []
+		}),
+		new web3._extend.Method({
+			name: 'setGlobalRegistrar',
+			call: 'admin_setGlobalRegistrar',
+			params: 2,
+			inputFormatter: [null,null]
+		}),
+		new web3._extend.Method({
+			name: 'setHashReg',
+			call: 'admin_setHashReg',
+			params: 2,
+			inputFormatter: [null,null]
+		}),
+		new web3._extend.Method({
+			name: 'setUrlHint',
+			call: 'admin_setUrlHint',
+			params: 2,
+			inputFormatter: [null,null]
+		}),
+		new web3._extend.Method({
+			name: 'saveInfo',
+			call: 'admin_saveInfo',
+			params: 2,
+			inputFormatter: [null,null]
+		}),
+		new web3._extend.Method({
+			name: 'register',
+			call: 'admin_register',
+			params: 3,
+			inputFormatter: [null,null,null]
+		}),
+		new web3._extend.Method({
+			name: 'registerUrl',
+			call: 'admin_registerUrl',
+			params: 3,
+			inputFormatter: [null,null,null]
+		}),
+		new web3._extend.Method({
+			name: 'startNatSpec',
+			call: 'admin_startNatSpec',
+			params: 0,
+			inputFormatter: []
+		}),
+		new web3._extend.Method({
+			name: 'stopNatSpec',
+			call: 'admin_stopNatSpec',
+			params: 0,
+			inputFormatter: []
+		}),
+		new web3._extend.Method({
+			name: 'getContractInfo',
+			call: 'admin_getContractInfo',
+			params: 1,
+			inputFormatter: [null],
+		}),
+		new web3._extend.Method({
+			name: 'httpGet',
+			call: 'admin_httpGet',
+			params: 2,
+			inputFormatter: [null, null]
 		})
 	],
 	properties:
 	[
 		new web3._extend.Property({
 			name: 'nodeInfo',
-			getter: 'admin_nodeInfo',
-			outputFormatter: web3._extend.formatters.formatOutputString
+			getter: 'admin_nodeInfo'
 		}),
 		new web3._extend.Property({
 			name: 'peers',
-			getter: 'admin_peers',
-			outputFormatter: function(obj) { return obj; }
+			getter: 'admin_peers'
 		}),
 		new web3._extend.Property({
 			name: 'datadir',
-			getter: 'admin_datadir',
-			outputFormatter: web3._extend.formatters.formatOutputString
+			getter: 'admin_datadir'
 		}),
 		new web3._extend.Property({
 			name: 'chainSyncStatus',
-			getter: 'admin_chainSyncStatus',
-			outputFormatter: function(obj) { return obj; }
+			getter: 'admin_chainSyncStatus'
 		})
 	]
 });
diff --git a/rpc/api/db_js.go b/rpc/api/db_js.go
index 62cdcd20eef4ed6538f9e321e8aa6d03a3a7f1fe..91dc95e5b5e886c77a24c9801931303b7e4ab5fb 100644
--- a/rpc/api/db_js.go
+++ b/rpc/api/db_js.go
@@ -5,34 +5,6 @@ web3._extend({
 	property: 'db',
 	methods:
 	[
-		new web3._extend.Method({
-			name: 'getString',
-			call: 'db_getString',
-			params: 2,
-			inputFormatter: [web3._extend.formatters.formatInputString, web3._extend.formatters.formatInputString],
-			outputFormatter: web3._extend.formatters.formatOutputString
-		}),
-		new web3._extend.Method({
-			name: 'putString',
-			call: 'db_putString',
-			params: 3,
-			inputFormatter: [web3._extend.formatters.formatInputString, web3._extend.formatters.formatInputString, web3._extend.formatters.formatInputString],
-			outputFormatter: web3._extend.formatters.formatOutputBool
-		}),
-		new web3._extend.Method({
-			name: 'getHex',
-			call: 'db_getHex',
-			params: 2,
-			inputFormatter: [web3._extend.formatters.formatInputString, web3._extend.formatters.formatInputString],
-			outputFormatter: web3._extend.formatters.formatOutputString
-		}),
-		new web3._extend.Method({
-			name: 'putHex',
-			call: 'db_putHex',
-			params: 3,
-			inputFormatter: [web3._extend.formatters.formatInputString, web3._extend.formatters.formatInputString, web3._extend.formatters.formatInputString],
-			outputFormatter: web3._extend.formatters.formatOutputBool
-		}),
 	],
 	properties:
 	[
diff --git a/rpc/api/debug_js.go b/rpc/api/debug_js.go
index bd3a6dfb24d38259aad67c1e8f106984f21d0ff9..93fba537e33a787c360179e408621a6f7fe5473a 100644
--- a/rpc/api/debug_js.go
+++ b/rpc/api/debug_js.go
@@ -9,50 +9,43 @@ web3._extend({
 			name: 'printBlock',
 			call: 'debug_printBlock',
 			params: 1,
-			inputFormatter: [web3._extend.formatters.formatInputInt],
-			outputFormatter: web3._extend.formatters.formatOutputString
+			inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter]
 		}),
 		new web3._extend.Method({
 			name: 'getBlockRlp',
 			call: 'debug_getBlockRlp',
 			params: 1,
-			inputFormatter: [web3._extend.formatters.formatInputInt],
-			outputFormatter: web3._extend.formatters.formatOutputString
+			inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter]
 		}),
 		new web3._extend.Method({
 			name: 'setHead',
 			call: 'debug_setHead',
 			params: 1,
-			inputFormatter: [web3._extend.formatters.formatInputInt],
-			outputFormatter: web3._extend.formatters.formatOutputBool
+			inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter]
 		}),
 		new web3._extend.Method({
 			name: 'processBlock',
 			call: 'debug_processBlock',
 			params: 1,
-			inputFormatter: [web3._extend.formatters.formatInputInt],
-			outputFormatter: function(obj) { return obj; }
+			inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter]
 		}),
 		new web3._extend.Method({
 			name: 'seedHash',
 			call: 'debug_seedHash',
 			params: 1,
-			inputFormatter: [web3._extend.formatters.formatInputInt],
-			outputFormatter: web3._extend.formatters.formatOutputString
-		})		,
+			inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter]
+		}),
 		new web3._extend.Method({
 			name: 'dumpBlock',
 			call: 'debug_dumpBlock',
 			params: 1,
-			inputFormatter: [web3._extend.formatters.formatInputInt],
-			outputFormatter: function(obj) { return obj; }
+			inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter]
 		}),
 		new web3._extend.Method({
 			name: 'metrics',
 			call: 'debug_metrics',
 			params: 1,
-			inputFormatter: [web3._extend.formatters.formatInputBool],
-			outputFormatter: function(obj) { return obj; }
+			inputFormatter: [null]
 		})
 	],
 	properties:
diff --git a/rpc/api/eth_js.go b/rpc/api/eth_js.go
index 4512cc147f0519a6e394c743b6bbac0fb120d561..400eb8e895a536867ca31464399088e1b0487095 100644
--- a/rpc/api/eth_js.go
+++ b/rpc/api/eth_js.go
@@ -12,23 +12,20 @@ web3._extend({
 			name: 'sign',
 			call: 'eth_sign',
 			params: 2,
-			inputFormatter: [web3._extend.formatters.formatInputString,web3._extend.formatters.formatInputString],
-			outputFormatter: web3._extend.formatters.formatOutputString
+			inputFormatter: [web3._extend.utils.toAddress, null]
 		}),
 		new web3._extend.Method({
 			name: 'resend',
 			call: 'eth_resend',
 			params: 3,
-			inputFormatter: [function(obj) { return obj; },web3._extend.formatters.formatInputString,web3._extend.formatters.formatInputString],
-			outputFormatter: web3._extend.formatters.formatOutputString
+			inputFormatter: [web3._extend.formatters.inputTransactionFormatter, web3._extend.utils.fromDecimal, web3._extend.utils.fromDecimal]
 		})
 	],
 	properties:
 	[
 		new web3._extend.Property({
 			name: 'pendingTransactions',
-			getter: 'eth_pendingTransactions',
-			outputFormatter: function(obj) { return obj; }
+			getter: 'eth_pendingTransactions'
 		})
 	]
 });
diff --git a/rpc/api/miner_js.go b/rpc/api/miner_js.go
index 6290368da3af75fabda3de4b52824621c4ee9f1d..8861a177ae5f516516f6e45d2622ce8ebdd22ec2 100644
--- a/rpc/api/miner_js.go
+++ b/rpc/api/miner_js.go
@@ -9,50 +9,43 @@ web3._extend({
 			name: 'start',
 			call: 'miner_start',
 			params: 1,
-			inputFormatter: [web3._extend.formatters.formatInputInt],
-			outputFormatter: web3._extend.formatters.formatOutputBool
+			inputFormatter: [null]
 		}),
 		new web3._extend.Method({
 			name: 'stop',
 			call: 'miner_stop',
 			params: 1,
-			inputFormatter: [web3._extend.formatters.formatInputInt],
-			outputFormatter: web3._extend.formatters.formatOutputBool
+			inputFormatter: [null]
 		}),
 		new web3._extend.Method({
 			name: 'setExtra',
 			call: 'miner_setExtra',
 			params: 1,
-			inputFormatter: [web3._extend.utils.formatInputString],
-			outputFormatter: web3._extend.formatters.formatOutputBool
+			inputFormatter: [null]
 		}),
 		new web3._extend.Method({
 			name: 'setGasPrice',
 			call: 'miner_setGasPrice',
 			params: 1,
-			inputFormatter: [web3._extend.utils.formatInputString],
-			outputFormatter: web3._extend.formatters.formatOutputBool
+			inputFormatter: [web3._extend.utils.fromDecial]
 		}),
 		new web3._extend.Method({
 			name: 'startAutoDAG',
 			call: 'miner_startAutoDAG',
 			params: 0,
-			inputFormatter: [],
-			outputFormatter: web3._extend.formatters.formatOutputBool
+			inputFormatter: []
 		}),
 		new web3._extend.Method({
 			name: 'stopAutoDAG',
 			call: 'miner_stopAutoDAG',
 			params: 0,
-			inputFormatter: [],
-			outputFormatter: web3._extend.formatters.formatOutputBool
+			inputFormatter: []
 		}),
 		new web3._extend.Method({
 			name: 'makeDAG',
 			call: 'miner_makeDAG',
 			params: 1,
-			inputFormatter: [web3._extend.formatters.inputDefaultBlockNumberFormatter],
-			outputFormatter: web3._extend.formatters.formatOutputBool
+			inputFormatter: [web3._extend.formatters.inputDefaultBlockNumberFormatter]
 		})
 	],
 	properties:
diff --git a/rpc/api/net.go b/rpc/api/net.go
index 7616546610e42a0f162083f1d54fd326b6025221..b3931ba2df29b1e687d932d5e32a4e22766b3471 100644
--- a/rpc/api/net.go
+++ b/rpc/api/net.go
@@ -14,10 +14,8 @@ const (
 var (
 	// mapping between methods and handlers
 	netMapping = map[string]nethandler{
-		"net_version":   (*netApi).Version,
 		"net_peerCount": (*netApi).PeerCount,
 		"net_listening": (*netApi).IsListening,
-		"net_peers":     (*netApi).Peers,
 	}
 )
 
@@ -70,11 +68,6 @@ func (self *netApi) ApiVersion() string {
 	return NetApiVersion
 }
 
-// Network version
-func (self *netApi) Version(req *shared.Request) (interface{}, error) {
-	return self.xeth.NetworkVersion(), nil
-}
-
 // Number of connected peers
 func (self *netApi) PeerCount(req *shared.Request) (interface{}, error) {
 	return newHexNum(self.xeth.PeerCount()), nil
@@ -84,6 +77,3 @@ func (self *netApi) IsListening(req *shared.Request) (interface{}, error) {
 	return self.xeth.IsListening(), nil
 }
 
-func (self *netApi) Peers(req *shared.Request) (interface{}, error) {
-	return self.ethereum.PeersInfo(), nil
-}
diff --git a/rpc/api/net_js.go b/rpc/api/net_js.go
index 1677d9fa6454fd970c447c653eb98a6b126331b5..2f872393c9f8a41e24b3aefbe37fc5bb5d0397d5 100644
--- a/rpc/api/net_js.go
+++ b/rpc/api/net_js.go
@@ -2,46 +2,18 @@ package api
 
 const Net_JS = `
 web3._extend({
-	property: 'network',
+	property: 'net',
 	methods:
 	[
 		new web3._extend.Method({
 			name: 'addPeer',
 			call: 'net_addPeer',
 			params: 1,
-			inputFormatter: [web3._extend.utils.formatInputString],
-			outputFormatter: web3._extend.formatters.formatOutputBool
-		}),
-		new web3._extend.Method({
-			name: 'getPeerCount',
-			call: 'net_peerCount',
-			params: 0,
-			inputFormatter: [],
-			outputFormatter: web3._extend.formatters.formatOutputString
+			inputFormatter: [null]
 		})
 	],
 	properties:
 	[
-		new web3._extend.Property({
-			name: 'listening',
-			getter: 'net_listening',
-			outputFormatter: web3._extend.formatters.formatOutputBool
-		}),
-		new web3._extend.Property({
-			name: 'peerCount',
-			getter: 'net_peerCount',
-			outputFormatter: web3._extend.utils.toDecimal
-		}),
-		new web3._extend.Property({
-			name: 'peers',
-			getter: 'net_peers',
-			outputFormatter: function(obj) { return obj; }
-		}),
-		new web3._extend.Property({
-			name: 'version',
-			getter: 'net_version',
-			outputFormatter: web3._extend.formatters.formatOutputString
-		})
 	]
 });
 `
diff --git a/rpc/api/personal_js.go b/rpc/api/personal_js.go
index 463a2c7f50d5ce8dd5adbcbda12ed7114ca954f8..66014cc02de9c06f5087ed1ca52183c6620e9f98 100644
--- a/rpc/api/personal_js.go
+++ b/rpc/api/personal_js.go
@@ -9,23 +9,21 @@ web3._extend({
 			name: 'newAccount',
 			call: 'personal_newAccount',
 			params: 1,
-			inputFormatter: [web3._extend.formatters.formatInputString],
-			outputFormatter: web3._extend.formatters.formatOutputString
+			inputFormatter: [null],
+			outputFormatter: web3._extend.utils.toAddress
 		}),
 		new web3._extend.Method({
 			name: 'unlockAccount',
 			call: 'personal_unlockAccount',
 			params: 3,
-			inputFormatter: [web3._extend.formatters.formatInputString,web3._extend.formatters.formatInputString,web3._extend.formatters.formatInputInt],
-			outputFormatter: web3._extend.formatters.formatOutputBool
+			inputFormatter: [null, null, null]
 		})
 	],
 	properties:
 	[
 		new web3._extend.Property({
 			name: 'listAccounts',
-			getter: 'personal_listAccounts',
-			outputFormatter: function(obj) { return obj; }
+			getter: 'personal_listAccounts'
 		})
 	]
 });
diff --git a/rpc/api/ssh_js.go b/rpc/api/ssh_js.go
index f401f70f197cd811f120f087e1fa884c4919b910..c0591bd71d9df908d8a25a6500b4d2a868e57b19 100644
--- a/rpc/api/ssh_js.go
+++ b/rpc/api/ssh_js.go
@@ -5,25 +5,13 @@ web3._extend({
 	property: 'shh',
 	methods:
 	[
-		new web3._extend.Method({
-			name: 'post',
-			call: 'shh_post',
-			params: 6,
-			inputFormatter: [web3._extend.formatters.formatInputString,
-							  web3._extend.formatters.formatInputString,
-							  web3._extend.formatters.formatInputString,
-							,
-							, web3._extend.formatters.formatInputInt
-							, web3._extend.formatters.formatInputInt],
-			outputFormatter: web3._extend.formatters.formatOutputBool
-		}),
+
 	],
 	properties:
 	[
 		new web3._extend.Property({
 			name: 'version',
-			getter: 'shh_version',
-			outputFormatter: web3._extend.formatters.formatOutputInt
+			getter: 'shh_version'
 		})
 	]
 });
diff --git a/rpc/api/utils.go b/rpc/api/utils.go
index 54ca28774d08bbe5a76829a7d77e1484cd3e20ee..d64cfc7cfc50f2061acb9154416985ea77371822 100644
--- a/rpc/api/utils.go
+++ b/rpc/api/utils.go
@@ -36,6 +36,7 @@ var (
 		"debug": []string{
 			"dumpBlock",
 			"getBlockRlp",
+			"metrics",
 			"printBlock",
 			"processBlock",
 			"seedHash",
@@ -44,49 +45,38 @@ var (
 		"eth": []string{
 			"accounts",
 			"blockNumber",
-			"getBalance",
-			"protocolVersion",
+			"call",
+			"contract",
 			"coinbase",
-			"mining",
+			"compile.lll",
+			"compile.serpent",
+			"compile.solidity",
+			"contract",
+			"defaultAccount",
+			"defaultBlock",
+			"estimateGas",
+			"filter",
+			"getBalance",
+			"getBlock",
+			"getBlockTransactionCount",
+			"getBlockUncleCount",
+			"getCode",
+			"getCompilers",
 			"gasPrice",
-			"getStorage",
-			"storageAt",
 			"getStorageAt",
+			"getTransaction",
 			"getTransactionCount",
-			"getBlockTransactionCountByHash",
-			"getBlockTransactionCountByNumber",
-			"getUncleCountByBlockHash",
-			"getUncleCountByBlockNumber",
-			"getData",
-			"getCode",
-			"sign",
-			"sendRawTransaction",
-			"sendTransaction",
-			"transact",
-			"estimateGas",
-			"call",
-			"flush",
-			"getBlockByHash",
-			"getBlockByNumber",
-			"getTransactionByHash",
-			"getTransactionByBlockHashAndIndex",
-			"getUncleByBlockHashAndIndex",
-			"getUncleByBlockNumberAndIndex",
-			"getCompilers",
-			"compileSolidity",
-			"newFilter",
-			"newBlockFilter",
-			"newPendingTransactionFilter",
-			"uninstallFilter",
-			"getFilterChanges",
-			"getFilterLogs",
-			"getLogs",
+			"getTransactionFromBlock",
+			"getTransactionReceipt",
+			"getUncle",
 			"hashrate",
-			"getWork",
-			"submitWork",
+			"mining",
+			"namereg",
 			"pendingTransactions",
 			"resend",
-			"getTransactionReceipt",
+			"sendRawTransaction",
+			"sendTransaction",
+			"sign",
 		},
 		"miner": []string{
 			"hashrate",
@@ -109,13 +99,12 @@ var (
 			"unlockAccount",
 		},
 		"shh": []string{
-			"version",
 			"post",
+			"newIdentify",
 			"hasIdentity",
-			"newIdentity",
-			"newFilter",
-			"uninstallFilter",
-			"getFilterChanges",
+			"newGroup",
+			"addToGroup",
+			"filter",
 		},
 		"txpool": []string{
 			"status",
diff --git a/xeth/xeth.go b/xeth/xeth.go
index f2295e6e157da07c261e3f99958b767921ebb5c9..a3923436afae0f566c0620fee5badee2263bd118 100644
--- a/xeth/xeth.go
+++ b/xeth/xeth.go
@@ -203,34 +203,6 @@ func (self *XEth) AtStateNum(num int64) *XEth {
 	return self.WithState(st)
 }
 
-// applies queued transactions originating from address onto the latest state
-// and creates a block
-// only used in tests
-// - could be removed in favour of mining on testdag (natspec e2e + networking)
-// + filters
-func (self *XEth) ApplyTestTxs(statedb *state.StateDB, address common.Address, txc uint64) (uint64, *XEth) {
-	chain := self.backend.ChainManager()
-	header := chain.CurrentBlock().Header()
-	coinbase := statedb.GetStateObject(address)
-	coinbase.SetGasLimit(big.NewInt(10000000))
-	txs := self.backend.TxPool().GetQueuedTransactions()
-
-	for i := 0; i < len(txs); i++ {
-		for _, tx := range txs {
-			if tx.Nonce() == txc {
-				_, _, err := core.ApplyMessage(core.NewEnv(statedb, self.backend.ChainManager(), tx, header), tx, coinbase)
-				if err != nil {
-					panic(err)
-				}
-				txc++
-			}
-		}
-	}
-
-	xeth := self.WithState(statedb)
-	return txc, xeth
-}
-
 func (self *XEth) WithState(statedb *state.StateDB) *XEth {
 	xeth := &XEth{
 		backend:  self.backend,