diff --git a/cmd/geth/js.go b/cmd/geth/js.go
index 7f7f19d78aefb9c84932c3813b9fa54285c0d1d5..4d5462539bb496808dee55f5ec50e4255a61d9e6 100644
--- a/cmd/geth/js.go
+++ b/cmd/geth/js.go
@@ -30,7 +30,6 @@ import (
 
 	"github.com/ethereum/go-ethereum/cmd/utils"
 	"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"
@@ -77,8 +76,6 @@ func (r dumbterm) PasswordPrompt(p string) (string, error) {
 func (r dumbterm) AppendHistory(string) {}
 
 type jsre struct {
-	docRoot    string
-	ds         *docserver.DocServer
 	re         *re.JSRE
 	ethereum   *eth.Ethereum
 	xeth       *xeth.XEth
@@ -153,7 +150,6 @@ func newLightweightJSRE(docRoot string, client comms.EthereumClient, datadir str
 	js := &jsre{ps1: "> "}
 	js.wait = make(chan *big.Int)
 	js.client = client
-	js.ds = docserver.New(docRoot)
 
 	// update state in separare forever blocks
 	js.re = re.New(docRoot)
@@ -181,18 +177,17 @@ func newLightweightJSRE(docRoot string, client comms.EthereumClient, datadir str
 }
 
 func newJSRE(ethereum *eth.Ethereum, docRoot, corsDomain string, client comms.EthereumClient, interactive bool, f xeth.Frontend) *jsre {
-	js := &jsre{ethereum: ethereum, ps1: "> ", docRoot: docRoot}
+	js := &jsre{ethereum: ethereum, ps1: "> "}
 	// set default cors domain used by startRpc from CLI flag
 	js.corsDomain = corsDomain
 	if f == nil {
 		f = js
 	}
-	js.ds = docserver.New(docRoot)
 	js.xeth = xeth.New(ethereum, f)
 	js.wait = js.xeth.UpdateState()
 	js.client = client
 	if clt, ok := js.client.(*comms.InProcClient); ok {
-		if offeredApis, err := api.ParseApiString(shared.AllApis, codec.JSON, js.xeth, ethereum, docRoot); err == nil {
+		if offeredApis, err := api.ParseApiString(shared.AllApis, codec.JSON, js.xeth, ethereum); err == nil {
 			clt.Initialize(api.Merge(offeredApis...))
 		}
 	}
@@ -248,14 +243,14 @@ func (self *jsre) batch(statement string) {
 // show summary of current geth instance
 func (self *jsre) welcome() {
 	self.re.Run(`
-		(function () {
-			console.log('instance: ' + web3.version.client);
-			console.log(' datadir: ' + admin.datadir);
-			console.log("coinbase: " + eth.coinbase);
-			var ts = 1000 * eth.getBlock(eth.blockNumber).timestamp;
-			console.log("at block: " + eth.blockNumber + " (" + new Date(ts) + ")");
-		})();
-	`)
+    (function () {
+      console.log('instance: ' + web3.version.client);
+      console.log(' datadir: ' + admin.datadir);
+      console.log("coinbase: " + eth.coinbase);
+      var ts = 1000 * eth.getBlock(eth.blockNumber).timestamp;
+      console.log("at block: " + eth.blockNumber + " (" + new Date(ts) + ")");
+    })();
+  `)
 	if modules, err := self.supportedApis(); err == nil {
 		loadedModules := make([]string, 0)
 		for api, version := range modules {
@@ -281,7 +276,7 @@ func (js *jsre) apiBindings(f xeth.Frontend) error {
 		apiNames = append(apiNames, a)
 	}
 
-	apiImpl, err := api.ParseApiString(strings.Join(apiNames, ","), codec.JSON, js.xeth, js.ethereum, js.docRoot)
+	apiImpl, err := api.ParseApiString(strings.Join(apiNames, ","), codec.JSON, js.xeth, js.ethereum)
 	if err != nil {
 		utils.Fatalf("Unable to determine supported api's: %v", err)
 	}
@@ -334,7 +329,7 @@ func (js *jsre) apiBindings(f xeth.Frontend) error {
 		utils.Fatalf("Error setting namespaces: %v", err)
 	}
 
-	js.re.Run(`var GlobalRegistrar = eth.contract(` + registrar.GlobalRegistrarAbi + `);	 registrar = GlobalRegistrar.at("` + registrar.GlobalRegistrarAddr + `");`)
+	js.re.Run(`var GlobalRegistrar = eth.contract(` + registrar.GlobalRegistrarAbi + `);   registrar = GlobalRegistrar.at("` + registrar.GlobalRegistrarAddr + `");`)
 	return nil
 }
 
@@ -348,7 +343,7 @@ func (self *jsre) AskPassword() (string, bool) {
 
 func (self *jsre) ConfirmTransaction(tx string) bool {
 	if self.ethereum.NatSpec {
-		notice := natspec.GetNotice(self.xeth, tx, self.ds)
+		notice := natspec.GetNotice(self.xeth, tx, self.ethereum.HTTPClient())
 		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 09cc88519c59913da334190b39fc03739ad2f95b..477079706253137996ee013032e1b3f16b5d8f52 100644
--- a/cmd/geth/js_test.go
+++ b/cmd/geth/js_test.go
@@ -31,7 +31,7 @@ import (
 	"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/httpclient"
 	"github.com/ethereum/go-ethereum/common/natspec"
 	"github.com/ethereum/go-ethereum/common/registrar"
 	"github.com/ethereum/go-ethereum/core"
@@ -62,7 +62,7 @@ var (
 type testjethre struct {
 	*jsre
 	lastConfirm string
-	ds          *docserver.DocServer
+	client      *httpclient.HTTPClient
 }
 
 func (self *testjethre) UnlockAccount(acc []byte) bool {
@@ -75,7 +75,7 @@ func (self *testjethre) UnlockAccount(acc []byte) bool {
 
 func (self *testjethre) ConfirmTransaction(tx string) bool {
 	if self.ethereum.NatSpec {
-		self.lastConfirm = natspec.GetNotice(self.xeth, tx, self.ds)
+		self.lastConfirm = natspec.GetNotice(self.xeth, tx, self.client)
 	}
 	return true
 }
@@ -101,6 +101,7 @@ func testREPL(t *testing.T, config func(*eth.Config)) (string, *testjethre, *eth
 		AccountManager: am,
 		MaxPeers:       0,
 		Name:           "test",
+		DocRoot:        "/",
 		SolcPath:       testSolcPath,
 		PowTest:        true,
 		NewDB:          func(path string) (ethdb.Database, error) { return db, nil },
@@ -130,8 +131,7 @@ func testREPL(t *testing.T, config func(*eth.Config)) (string, *testjethre, *eth
 
 	assetPath := filepath.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist", "assets", "ext")
 	client := comms.NewInProcClient(codec.JSON)
-	ds := docserver.New("/")
-	tf := &testjethre{ds: ds}
+	tf := &testjethre{client: ethereum.HTTPClient()}
 	repl := newJSRE(ethereum, assetPath, "", client, false, tf)
 	tf.jsre = repl
 	return tmp, tf, ethereum
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 66ec46f8077a83b18888ffa0ef8530c812ca382d..79c86c52a52bf1dbeacfb9c2b61cd6d3fd293809 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -139,6 +139,11 @@ var (
 		Name:  "natspec",
 		Usage: "Enable NatSpec confirmation notice",
 	}
+	DocRootFlag = DirectoryFlag{
+		Name:  "docroot",
+		Usage: "Document Root for HTTPClient file scheme",
+		Value: DirectoryString{common.HomeDir()},
+	}
 	CacheFlag = cli.IntFlag{
 		Name:  "cache",
 		Usage: "Megabytes of memory allocated to internal caching",
@@ -452,6 +457,7 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
 		Olympic:                 ctx.GlobalBool(OlympicFlag.Name),
 		NAT:                     MakeNAT(ctx),
 		NatSpec:                 ctx.GlobalBool(NatspecEnabledFlag.Name),
+		DocRoot:                 ctx.GlobalString(DocRootFlag.Name),
 		Discovery:               !ctx.GlobalBool(NoDiscoverFlag.Name),
 		NodeKey:                 MakeNodeKey(ctx),
 		Shh:                     ctx.GlobalBool(WhisperEnabledFlag.Name),
@@ -616,7 +622,7 @@ func StartIPC(eth *eth.Ethereum, ctx *cli.Context) error {
 		xeth := xeth.New(eth, fe)
 		codec := codec.JSON
 
-		apis, err := api.ParseApiString(ctx.GlobalString(IPCApiFlag.Name), codec, xeth, eth, ctx.GlobalString(JSpathFlag.Name))
+		apis, err := api.ParseApiString(ctx.GlobalString(IPCApiFlag.Name), codec, xeth, eth)
 		if err != nil {
 			return nil, err
 		}
@@ -637,7 +643,7 @@ func StartRPC(eth *eth.Ethereum, ctx *cli.Context) error {
 	xeth := xeth.New(eth, nil)
 	codec := codec.JSON
 
-	apis, err := api.ParseApiString(ctx.GlobalString(RpcApiFlag.Name), codec, xeth, eth, ctx.GlobalString(JSpathFlag.Name))
+	apis, err := api.ParseApiString(ctx.GlobalString(RpcApiFlag.Name), codec, xeth, eth)
 	if err != nil {
 		return err
 	}
diff --git a/common/docserver/docserver.go b/common/httpclient/httpclient.go
similarity index 74%
rename from common/docserver/docserver.go
rename to common/httpclient/httpclient.go
index cfc4e3b26aae1275689122d9028cf8c7632a3add..23373ecaf5cc7cca32a1e0812e4c48443dc6abcc 100644
--- a/common/docserver/docserver.go
+++ b/common/httpclient/httpclient.go
@@ -14,7 +14,7 @@
 // You should have received a copy of the GNU Lesser General Public License
 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
 
-package docserver
+package httpclient
 
 import (
 	"fmt"
@@ -26,14 +26,14 @@ import (
 	"github.com/ethereum/go-ethereum/crypto"
 )
 
-type DocServer struct {
+type HTTPClient struct {
 	*http.Transport
 	DocRoot string
 	schemes []string
 }
 
-func New(docRoot string) (self *DocServer) {
-	self = &DocServer{
+func New(docRoot string) (self *HTTPClient) {
+	self = &HTTPClient{
 		Transport: &http.Transport{},
 		DocRoot:   docRoot,
 		schemes:   []string{"file"},
@@ -46,18 +46,18 @@ func New(docRoot string) (self *DocServer) {
 
 // A Client is higher-level than a RoundTripper (such as Transport) and additionally handles HTTP details such as cookies and redirects.
 
-func (self *DocServer) Client() *http.Client {
+func (self *HTTPClient) Client() *http.Client {
 	return &http.Client{
 		Transport: self,
 	}
 }
 
-func (self *DocServer) RegisterScheme(scheme string, rt http.RoundTripper) {
+func (self *HTTPClient) RegisterScheme(scheme string, rt http.RoundTripper) {
 	self.schemes = append(self.schemes, scheme)
 	self.RegisterProtocol(scheme, rt)
 }
 
-func (self *DocServer) HasScheme(scheme string) bool {
+func (self *HTTPClient) HasScheme(scheme string) bool {
 	for _, s := range self.schemes {
 		if s == scheme {
 			return true
@@ -66,43 +66,41 @@ func (self *DocServer) HasScheme(scheme string) bool {
 	return false
 }
 
-func (self *DocServer) GetAuthContent(uri string, hash common.Hash) (content []byte, err error) {
+func (self *HTTPClient) GetAuthContent(uri string, hash common.Hash) ([]byte, error) {
 	// retrieve content
-	content, err = self.Get(uri, "")
+	content, err := self.Get(uri, "")
 	if err != nil {
-		return
+		return nil, err
 	}
 
 	// 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 nil, fmt.Errorf("content hash mismatch %x != %x (exp)", hash[:], chash[:])
 	}
 
-	return
+	return content, nil
 
 }
 
 // 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) {
+func (self *HTTPClient) Get(uri, path string) ([]byte, error) {
 	// retrieve content
 	resp, err := self.Client().Get(uri)
-
+	if err != nil {
+		return nil, err
+	}
 	defer func() {
 		if resp != nil {
 			resp.Body.Close()
 		}
 	}()
 
-	if err != nil {
-		return
-	}
-
+	var content []byte
 	content, err = ioutil.ReadAll(resp.Body)
 	if err != nil {
-		return
+		return nil, err
 	}
 
 	if resp.StatusCode/100 != 2 {
@@ -112,9 +110,15 @@ func (self *DocServer) Get(uri, path string) (content []byte, err error) {
 	if path != "" {
 		var abspath string
 		abspath, err = filepath.Abs(path)
-		ioutil.WriteFile(abspath, content, 0700)
+		if err != nil {
+			return nil, err
+		}
+		err = ioutil.WriteFile(abspath, content, 0600)
+		if err != nil {
+			return nil, err
+		}
 	}
 
-	return
+	return content, nil
 
 }
diff --git a/common/docserver/docserver_test.go b/common/httpclient/httpclient_test.go
similarity index 85%
rename from common/docserver/docserver_test.go
rename to common/httpclient/httpclient_test.go
index 632603addbe8cc10531108c1fb6cef5d1a725cc3..6c3782e15a3daa8c3244e862a38dac00573d56bc 100644
--- a/common/docserver/docserver_test.go
+++ b/common/httpclient/httpclient_test.go
@@ -14,7 +14,7 @@
 // You should have received a copy of the GNU Lesser General Public License
 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
 
-package docserver
+package httpclient
 
 import (
 	"io/ioutil"
@@ -28,19 +28,19 @@ import (
 )
 
 func TestGetAuthContent(t *testing.T) {
-	dir, err := ioutil.TempDir("", "docserver-test")
+	dir, err := ioutil.TempDir("", "httpclient-test")
 	if err != nil {
 		t.Fatal("cannot create temporary directory:", err)
 	}
 	defer os.RemoveAll(dir)
-	ds := New(dir)
+	client := New(dir)
 
 	text := "test"
 	hash := crypto.Sha3Hash([]byte(text))
 	if err := ioutil.WriteFile(path.Join(dir, "test.content"), []byte(text), os.ModePerm); err != nil {
 		t.Fatal("could not write test file", err)
 	}
-	content, err := ds.GetAuthContent("file:///test.content", hash)
+	content, err := client.GetAuthContent("file:///test.content", hash)
 	if err != nil {
 		t.Errorf("no error expected, got %v", err)
 	}
@@ -49,7 +49,7 @@ func TestGetAuthContent(t *testing.T) {
 	}
 
 	hash = common.Hash{}
-	content, err = ds.GetAuthContent("file:///test.content", hash)
+	content, err = client.GetAuthContent("file:///test.content", hash)
 	expected := "content hash mismatch 0000000000000000000000000000000000000000000000000000000000000000 != 9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658 (exp)"
 	if err == nil {
 		t.Errorf("expected error, got nothing")
@@ -66,12 +66,12 @@ 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") {
+	client := New("/tmp/")
+	if client.HasScheme("scheme") {
 		t.Errorf("expected scheme not to be registered")
 	}
-	ds.RegisterScheme("scheme", rt{})
-	if !ds.HasScheme("scheme") {
+	client.RegisterScheme("scheme", rt{})
+	if !client.HasScheme("scheme") {
 		t.Errorf("expected scheme to be registered")
 	}
-}
\ No newline at end of file
+}
diff --git a/common/natspec/natspec.go b/common/natspec/natspec.go
index 0265c2e13fde067646a02d5882cb58b322e49213..d9627b4e1c35a149337a553a94f0fa98b5726b10 100644
--- a/common/natspec/natspec.go
+++ b/common/natspec/natspec.go
@@ -23,7 +23,7 @@ import (
 	"strings"
 
 	"github.com/ethereum/go-ethereum/common"
-	"github.com/ethereum/go-ethereum/common/docserver"
+	"github.com/ethereum/go-ethereum/common/httpclient"
 	"github.com/ethereum/go-ethereum/common/registrar"
 	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/xeth"
@@ -43,7 +43,7 @@ type NatSpec struct {
 // the implementation is frontend friendly in that it always gives back
 // a notice that is safe to display
 // :FIXME: the second return value is an error, which can be used to fine-tune bahaviour
-func GetNotice(xeth *xeth.XEth, tx string, http *docserver.DocServer) (notice string) {
+func GetNotice(xeth *xeth.XEth, tx string, http *httpclient.HTTPClient) (notice string) {
 	ns, err := New(xeth, tx, http)
 	if err != nil {
 		if ns == nil {
@@ -83,7 +83,7 @@ type contractInfo struct {
 	DeveloperDoc  json.RawMessage `json:"developerDoc"`
 }
 
-func New(xeth *xeth.XEth, jsontx string, http *docserver.DocServer) (self *NatSpec, err error) {
+func New(xeth *xeth.XEth, jsontx string, http *httpclient.HTTPClient) (self *NatSpec, err error) {
 
 	// extract contract address from tx
 	var tx jsonTx
@@ -104,7 +104,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, ds *docserver.DocServer) (content []byte, err error) {
+func FetchDocsForContract(contractAddress string, xeth *xeth.XEth, client *httpclient.HTTPClient) (content []byte, err error) {
 	// retrieve contract hash from state
 	codehex := xeth.CodeAt(contractAddress)
 	codeb := xeth.CodeAtBytes(contractAddress)
@@ -122,8 +122,8 @@ func FetchDocsForContract(contractAddress string, xeth *xeth.XEth, ds *docserver
 	if err != nil {
 		return
 	}
-	if ds.HasScheme("bzz") {
-		content, err = ds.Get("bzz://"+hash.Hex()[2:], "")
+	if client.HasScheme("bzz") {
+		content, err = client.Get("bzz://"+hash.Hex()[2:], "")
 		if err == nil { // non-fatal
 			return
 		}
@@ -137,7 +137,7 @@ func FetchDocsForContract(contractAddress string, xeth *xeth.XEth, ds *docserver
 	}
 
 	// get content via http client and authenticate content using hash
-	content, err = ds.GetAuthContent(uri, hash)
+	content, err = client.GetAuthContent(uri, hash)
 	if err != nil {
 		return
 	}
diff --git a/common/natspec/natspec_e2e_test.go b/common/natspec/natspec_e2e_test.go
index 4149314c36048659f40bd6af090fbe433388e6f1..706a294ecbf9932b5dba1f5289a3a8cebc6e6308 100644
--- a/common/natspec/natspec_e2e_test.go
+++ b/common/natspec/natspec_e2e_test.go
@@ -28,7 +28,7 @@ import (
 
 	"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/httpclient"
 	"github.com/ethereum/go-ethereum/common/registrar"
 	"github.com/ethereum/go-ethereum/core"
 	"github.com/ethereum/go-ethereum/crypto"
@@ -113,8 +113,8 @@ func (self *testFrontend) UnlockAccount(acc []byte) bool {
 
 func (self *testFrontend) ConfirmTransaction(tx string) bool {
 	if self.wantNatSpec {
-		ds := docserver.New("/tmp/")
-		self.lastConfirm = GetNotice(self.xeth, tx, ds)
+		client := httpclient.New("/tmp/")
+		self.lastConfirm = GetNotice(self.xeth, tx, client)
 	}
 	return true
 }
diff --git a/common/path.go b/common/path.go
index 1253c424ca3d10aa8cd287b544cacf987b7d01a6..39eacaceebf36c83bf93a39a8bbf9ab7814c598e 100644
--- a/common/path.go
+++ b/common/path.go
@@ -23,8 +23,6 @@ import (
 	"path/filepath"
 	"runtime"
 	"strings"
-
-	"github.com/kardianos/osext"
 )
 
 // MakeName creates a node name that follows the ethereum convention
@@ -65,48 +63,18 @@ func AbsolutePath(Datadir string, filename string) string {
 	return filepath.Join(Datadir, filename)
 }
 
-func DefaultAssetPath() string {
-	var assetPath string
-	pwd, _ := os.Getwd()
-	srcdir := filepath.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist")
-
-	// If the current working directory is the go-ethereum dir
-	// assume a debug build and use the source directory as
-	// asset directory.
-	if pwd == srcdir {
-		assetPath = filepath.Join(pwd, "assets")
+func HomeDir() (home string) {
+	if usr, err := user.Current(); err == nil {
+		home = usr.HomeDir
 	} else {
-		switch runtime.GOOS {
-		case "darwin":
-			// Get Binary Directory
-			exedir, _ := osext.ExecutableFolder()
-			assetPath = filepath.Join(exedir, "..", "Resources")
-		case "linux":
-			assetPath = filepath.Join("usr", "share", "mist")
-		case "windows":
-			assetPath = filepath.Join(".", "assets")
-		default:
-			assetPath = "."
-		}
-	}
-
-	// Check if the assetPath exists. If not, try the source directory
-	// This happens when binary is run from outside cmd/mist directory
-	if _, err := os.Stat(assetPath); os.IsNotExist(err) {
-		assetPath = filepath.Join(srcdir, "assets")
+		home = os.Getenv("HOME")
 	}
-
-	return assetPath
+	return
 }
 
 func DefaultDataDir() string {
 	// Try to place the data folder in the user's home dir
-	var home string
-	if usr, err := user.Current(); err == nil {
-		home = usr.HomeDir
-	} else {
-		home = os.Getenv("HOME")
-	}
+	home := HomeDir()
 	if home != "" {
 		if runtime.GOOS == "darwin" {
 			return filepath.Join(home, "Library", "Ethereum")
diff --git a/eth/backend.go b/eth/backend.go
index 6ce0d0eb0a102a73888e132e1ce3df723a8d6174..ee857e14656bbb9ee30f0685362d0381e66e9c91 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -35,6 +35,7 @@ import (
 	"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/httpclient"
 	"github.com/ethereum/go-ethereum/core"
 	"github.com/ethereum/go-ethereum/core/state"
 	"github.com/ethereum/go-ethereum/core/types"
@@ -106,6 +107,7 @@ type Config struct {
 	LogJSON   string
 	VmDebug   bool
 	NatSpec   bool
+	DocRoot   string
 	AutoDAG   bool
 	PowTest   bool
 	ExtraData []byte
@@ -249,6 +251,8 @@ type Ethereum struct {
 	GpobaseStepUp           int
 	GpobaseCorrectionFactor int
 
+	httpclient *httpclient.HTTPClient
+
 	net      *p2p.Server
 	eventMux *event.TypeMux
 	miner    *miner.Miner
@@ -400,6 +404,7 @@ func New(config *Config) (*Ethereum, error) {
 		GpobaseStepDown:         config.GpobaseStepDown,
 		GpobaseStepUp:           config.GpobaseStepUp,
 		GpobaseCorrectionFactor: config.GpobaseCorrectionFactor,
+		httpclient:              httpclient.New(config.DocRoot),
 	}
 
 	if config.PowTest {
@@ -702,6 +707,12 @@ func (self *Ethereum) StopAutoDAG() {
 	glog.V(logger.Info).Infof("Automatic pregeneration of ethash DAG OFF (ethash dir: %s)", ethash.DefaultDir)
 }
 
+// HTTPClient returns the light http client used for fetching offchain docs
+// (natspec, source for verification)
+func (self *Ethereum) HTTPClient() *httpclient.HTTPClient {
+	return self.httpclient
+}
+
 func (self *Ethereum) Solc() (*compiler.Solidity, error) {
 	var err error
 	if self.solc == nil {
diff --git a/rpc/api/admin.go b/rpc/api/admin.go
index eed8d8366e9c1a54a9baabcb3c09f78abf18d2e2..eb08fbc5deec924e7d96f99ba791f3e99e60b44b 100644
--- a/rpc/api/admin.go
+++ b/rpc/api/admin.go
@@ -25,7 +25,6 @@ import (
 
 	"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"
@@ -84,19 +83,15 @@ type adminApi struct {
 	ethereum *eth.Ethereum
 	codec    codec.Codec
 	coder    codec.ApiCoder
-	docRoot  string
-	ds       *docserver.DocServer
 }
 
 // create a new admin api instance
-func NewAdminApi(xeth *xeth.XEth, ethereum *eth.Ethereum, codec codec.Codec, docRoot string) *adminApi {
+func NewAdminApi(xeth *xeth.XEth, ethereum *eth.Ethereum, codec codec.Codec) *adminApi {
 	return &adminApi{
 		xeth:     xeth,
 		ethereum: ethereum,
 		codec:    codec,
 		coder:    codec.New(nil),
-		docRoot:  docRoot,
-		ds:       docserver.New(docRoot),
 	}
 }
 
@@ -258,7 +253,7 @@ func (self *adminApi) StartRPC(req *shared.Request) (interface{}, error) {
 		CorsDomain:    args.CorsDomain,
 	}
 
-	apis, err := ParseApiString(args.Apis, self.codec, self.xeth, self.ethereum, self.docRoot)
+	apis, err := ParseApiString(args.Apis, self.codec, self.xeth, self.ethereum)
 	if err != nil {
 		return false, err
 	}
@@ -439,7 +434,7 @@ func (self *adminApi) GetContractInfo(req *shared.Request) (interface{}, error)
 		return nil, shared.NewDecodeParamError(err.Error())
 	}
 
-	infoDoc, err := natspec.FetchDocsForContract(args.Contract, self.xeth, self.ds)
+	infoDoc, err := natspec.FetchDocsForContract(args.Contract, self.xeth, self.ethereum.HTTPClient())
 	if err != nil {
 		return nil, err
 	}
@@ -459,7 +454,7 @@ func (self *adminApi) HttpGet(req *shared.Request) (interface{}, error) {
 		return nil, shared.NewDecodeParamError(err.Error())
 	}
 
-	resp, err := self.ds.Get(args.Uri, args.Path)
+	resp, err := self.ethereum.HTTPClient().Get(args.Uri, args.Path)
 	if err != nil {
 		return nil, err
 	}
diff --git a/rpc/api/api_test.go b/rpc/api/api_test.go
index a4efb09c19a962bbe8433ad0449b0c45088d8e63..131ef68f813753c80943deb6c1c00fc077895df5 100644
--- a/rpc/api/api_test.go
+++ b/rpc/api/api_test.go
@@ -30,7 +30,7 @@ import (
 )
 
 func TestParseApiString(t *testing.T) {
-	apis, err := ParseApiString("", codec.JSON, nil, nil, "")
+	apis, err := ParseApiString("", codec.JSON, nil, nil)
 	if err == nil {
 		t.Errorf("Expected an err from parsing empty API string but got nil")
 	}
@@ -39,7 +39,7 @@ func TestParseApiString(t *testing.T) {
 		t.Errorf("Expected 0 apis from empty API string")
 	}
 
-	apis, err = ParseApiString("eth", codec.JSON, nil, nil, "")
+	apis, err = ParseApiString("eth", codec.JSON, nil, nil)
 	if err != nil {
 		t.Errorf("Expected nil err from parsing empty API string but got %v", err)
 	}
@@ -48,7 +48,7 @@ func TestParseApiString(t *testing.T) {
 		t.Errorf("Expected 1 apis but got %d - %v", apis, apis)
 	}
 
-	apis, err = ParseApiString("eth,eth", codec.JSON, nil, nil, "")
+	apis, err = ParseApiString("eth,eth", codec.JSON, nil, nil)
 	if err != nil {
 		t.Errorf("Expected nil err from parsing empty API string but got \"%v\"", err)
 	}
@@ -57,7 +57,7 @@ func TestParseApiString(t *testing.T) {
 		t.Errorf("Expected 2 apis but got %d - %v", apis, apis)
 	}
 
-	apis, err = ParseApiString("eth,invalid", codec.JSON, nil, nil, "")
+	apis, err = ParseApiString("eth,invalid", codec.JSON, nil, nil)
 	if err == nil {
 		t.Errorf("Expected an err but got no err")
 	}
diff --git a/rpc/api/eth.go b/rpc/api/eth.go
index 4722682ff353e9ab5b49601c74e53a76f4da8865..b84ae31da28b574ff944552cc1edef7d5ae572c0 100644
--- a/rpc/api/eth.go
+++ b/rpc/api/eth.go
@@ -24,6 +24,7 @@ import (
 	"fmt"
 
 	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/common/natspec"
 	"github.com/ethereum/go-ethereum/eth"
 	"github.com/ethereum/go-ethereum/rpc/codec"
 	"github.com/ethereum/go-ethereum/rpc/shared"
@@ -67,6 +68,7 @@ var (
 		"eth_getUncleCountByBlockNumber":          (*ethApi).GetUncleCountByBlockNumber,
 		"eth_getData":                             (*ethApi).GetData,
 		"eth_getCode":                             (*ethApi).GetData,
+		"eth_getNatSpec":                          (*ethApi).GetNatSpec,
 		"eth_sign":                                (*ethApi).Sign,
 		"eth_sendRawTransaction":                  (*ethApi).SendRawTransaction,
 		"eth_sendTransaction":                     (*ethApi).SendTransaction,
@@ -322,6 +324,18 @@ func (self *ethApi) SendTransaction(req *shared.Request) (interface{}, error) {
 	return v, nil
 }
 
+func (self *ethApi) GetNatSpec(req *shared.Request) (interface{}, error) {
+	args := new(NewTxArgs)
+	if err := self.codec.Decode(req.Params, &args); err != nil {
+		return nil, shared.NewDecodeParamError(err.Error())
+	}
+
+	var jsontx = fmt.Sprintf(`{"params":[{"to":"%s","data": "%s"}]}`, args.To, args.Data)
+	notice := natspec.GetNotice(self.xeth, jsontx, self.ethereum.HTTPClient())
+
+	return notice, nil
+}
+
 func (self *ethApi) EstimateGas(req *shared.Request) (interface{}, error) {
 	_, gas, err := self.doCall(req.Params)
 	if err != nil {
diff --git a/rpc/api/eth_js.go b/rpc/api/eth_js.go
index 393dac22f4fc918c69be39ccad733dfc9ae7b8e2..75c103c9db199dbf3df70d6f689641e9aa0fade6 100644
--- a/rpc/api/eth_js.go
+++ b/rpc/api/eth_js.go
@@ -35,6 +35,12 @@ web3._extend({
 			call: 'eth_resend',
 			params: 3,
 			inputFormatter: [web3._extend.formatters.inputTransactionFormatter, web3._extend.utils.fromDecimal, web3._extend.utils.fromDecimal]
+		}),
+    new web3._extend.Method({
+	    name: 'getNatSpec',
+	    call: 'eth_getNatSpec',
+	    params: 1,
+	    inputFormatter: [web3._extend.formatters.inputTransactionFormatter]
 		})
 	],
 	properties:
diff --git a/rpc/api/utils.go b/rpc/api/utils.go
index 719cb80746603ebae146345c04bc83e250210762..5a3ade46b90d4ac9853f093555f954815c3020a5 100644
--- a/rpc/api/utils.go
+++ b/rpc/api/utils.go
@@ -89,6 +89,7 @@ var (
 			"getBlockTransactionCount",
 			"getBlockUncleCount",
 			"getCode",
+			"getNatSpec",
 			"getCompilers",
 			"gasPrice",
 			"getStorageAt",
@@ -153,7 +154,7 @@ var (
 )
 
 // Parse a comma separated API string to individual api's
-func ParseApiString(apistr string, codec codec.Codec, xeth *xeth.XEth, eth *eth.Ethereum, docRoot string) ([]shared.EthereumApi, error) {
+func ParseApiString(apistr string, codec codec.Codec, xeth *xeth.XEth, eth *eth.Ethereum) ([]shared.EthereumApi, error) {
 	if len(strings.TrimSpace(apistr)) == 0 {
 		return nil, fmt.Errorf("Empty apistr provided")
 	}
@@ -164,7 +165,7 @@ func ParseApiString(apistr string, codec codec.Codec, xeth *xeth.XEth, eth *eth.
 	for i, name := range names {
 		switch strings.ToLower(strings.TrimSpace(name)) {
 		case shared.AdminApiName:
-			apis[i] = NewAdminApi(xeth, eth, codec, docRoot)
+			apis[i] = NewAdminApi(xeth, eth, codec)
 		case shared.DebugApiName:
 			apis[i] = NewDebugApi(xeth, eth, codec)
 		case shared.DbApiName: