Merge pull request #3346 from obscuren/registrar-removal
common/registrar, eth: removed registrar (tech debt)
This commit is contained in:
		
						commit
						9c3ea0d32d
					
				| @ -373,7 +373,7 @@ var ( | ||||
| 	// ATM the url is left to the user and deployment to
 | ||||
| 	JSpathFlag = cli.StringFlag{ | ||||
| 		Name:  "jspath", | ||||
| 		Usage: "JavaScript root path for `loadScript` and document root for `admin.httpGet`", | ||||
| 		Usage: "JavaScript root path for `loadScript`", | ||||
| 		Value: ".", | ||||
| 	} | ||||
| 	SolcPathFlag = cli.StringFlag{ | ||||
|  | ||||
| @ -1,124 +0,0 @@ | ||||
| // Copyright 2015 The go-ethereum Authors
 | ||||
| // This file is part of the go-ethereum library.
 | ||||
| //
 | ||||
| // The go-ethereum library is free software: you can redistribute it and/or modify
 | ||||
| // it under the terms of the GNU Lesser General Public License as published by
 | ||||
| // the Free Software Foundation, either version 3 of the License, or
 | ||||
| // (at your option) any later version.
 | ||||
| //
 | ||||
| // The go-ethereum library is distributed in the hope that it will be useful,
 | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | ||||
| // GNU Lesser General Public License for more details.
 | ||||
| //
 | ||||
| // You should have received a copy of the GNU Lesser General Public License
 | ||||
| // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
 | ||||
| 
 | ||||
| package httpclient | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"net/http" | ||||
| 	"path/filepath" | ||||
| 
 | ||||
| 	"github.com/ethereum/go-ethereum/common" | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| ) | ||||
| 
 | ||||
| type HTTPClient struct { | ||||
| 	*http.Transport | ||||
| 	DocRoot string | ||||
| 	schemes []string | ||||
| } | ||||
| 
 | ||||
| func New(docRoot string) (self *HTTPClient) { | ||||
| 	self = &HTTPClient{ | ||||
| 		Transport: &http.Transport{}, | ||||
| 		DocRoot:   docRoot, | ||||
| 		schemes:   []string{"file"}, | ||||
| 	} | ||||
| 	self.RegisterProtocol("file", http.NewFileTransport(http.Dir(self.DocRoot))) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // Clients should be reused instead of created as needed. Clients are safe for concurrent use by multiple goroutines.
 | ||||
| 
 | ||||
| // A Client is higher-level than a RoundTripper (such as Transport) and additionally handles HTTP details such as cookies and redirects.
 | ||||
| 
 | ||||
| func (self *HTTPClient) Client() *http.Client { | ||||
| 	return &http.Client{ | ||||
| 		Transport: self, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (self *HTTPClient) RegisterScheme(scheme string, rt http.RoundTripper) { | ||||
| 	self.schemes = append(self.schemes, scheme) | ||||
| 	self.RegisterProtocol(scheme, rt) | ||||
| } | ||||
| 
 | ||||
| func (self *HTTPClient) HasScheme(scheme string) bool { | ||||
| 	for _, s := range self.schemes { | ||||
| 		if s == scheme { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| func (self *HTTPClient) GetAuthContent(uri string, hash common.Hash) ([]byte, error) { | ||||
| 	// retrieve content
 | ||||
| 	content, err := self.Get(uri, "") | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	// check hash to authenticate content
 | ||||
| 	chash := crypto.Keccak256Hash(content) | ||||
| 	if chash != hash { | ||||
| 		return nil, fmt.Errorf("content hash mismatch %x != %x (exp)", hash[:], chash[:]) | ||||
| 	} | ||||
| 
 | ||||
| 	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 *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() | ||||
| 		} | ||||
| 	}() | ||||
| 
 | ||||
| 	var content []byte | ||||
| 	content, err = ioutil.ReadAll(resp.Body) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	if resp.StatusCode/100 != 2 { | ||||
| 		return content, fmt.Errorf("HTTP error: %s", resp.Status) | ||||
| 	} | ||||
| 
 | ||||
| 	if path != "" { | ||||
| 		var abspath string | ||||
| 		abspath, err = filepath.Abs(path) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		err = ioutil.WriteFile(abspath, content, 0600) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return content, nil | ||||
| 
 | ||||
| } | ||||
| @ -1,77 +0,0 @@ | ||||
| // Copyright 2015 The go-ethereum Authors
 | ||||
| // This file is part of the go-ethereum library.
 | ||||
| //
 | ||||
| // The go-ethereum library is free software: you can redistribute it and/or modify
 | ||||
| // it under the terms of the GNU Lesser General Public License as published by
 | ||||
| // the Free Software Foundation, either version 3 of the License, or
 | ||||
| // (at your option) any later version.
 | ||||
| //
 | ||||
| // The go-ethereum library is distributed in the hope that it will be useful,
 | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | ||||
| // GNU Lesser General Public License for more details.
 | ||||
| //
 | ||||
| // You should have received a copy of the GNU Lesser General Public License
 | ||||
| // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
 | ||||
| 
 | ||||
| package httpclient | ||||
| 
 | ||||
| import ( | ||||
| 	"io/ioutil" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"path" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/ethereum/go-ethereum/common" | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| ) | ||||
| 
 | ||||
| func TestGetAuthContent(t *testing.T) { | ||||
| 	dir, err := ioutil.TempDir("", "httpclient-test") | ||||
| 	if err != nil { | ||||
| 		t.Fatal("cannot create temporary directory:", err) | ||||
| 	} | ||||
| 	defer os.RemoveAll(dir) | ||||
| 	client := New(dir) | ||||
| 
 | ||||
| 	text := "test" | ||||
| 	hash := crypto.Keccak256Hash([]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 := client.GetAuthContent("file:///test.content", hash) | ||||
| 	if err != nil { | ||||
| 		t.Errorf("no error expected, got %v", err) | ||||
| 	} | ||||
| 	if string(content) != text { | ||||
| 		t.Errorf("incorrect content. expected %v, got %v", text, string(content)) | ||||
| 	} | ||||
| 
 | ||||
| 	hash = common.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") | ||||
| 	} else { | ||||
| 		if err.Error() != expected { | ||||
| 			t.Errorf("expected error '%s' got '%v'", expected, err) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| type rt struct{} | ||||
| 
 | ||||
| func (rt) RoundTrip(req *http.Request) (resp *http.Response, err error) { return } | ||||
| 
 | ||||
| func TestRegisterScheme(t *testing.T) { | ||||
| 	client := New("/tmp/") | ||||
| 	if client.HasScheme("scheme") { | ||||
| 		t.Errorf("expected scheme not to be registered") | ||||
| 	} | ||||
| 	client.RegisterScheme("scheme", rt{}) | ||||
| 	if !client.HasScheme("scheme") { | ||||
| 		t.Errorf("expected scheme to be registered") | ||||
| 	} | ||||
| } | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -1,279 +0,0 @@ | ||||
| // Copyright 2015 The go-ethereum Authors
 | ||||
| // This file is part of the go-ethereum library.
 | ||||
| //
 | ||||
| // The go-ethereum library is free software: you can redistribute it and/or modify
 | ||||
| // it under the terms of the GNU Lesser General Public License as published by
 | ||||
| // the Free Software Foundation, either version 3 of the License, or
 | ||||
| // (at your option) any later version.
 | ||||
| //
 | ||||
| // The go-ethereum library is distributed in the hope that it will be useful,
 | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | ||||
| // GNU Lesser General Public License for more details.
 | ||||
| //
 | ||||
| // You should have received a copy of the GNU Lesser General Public License
 | ||||
| // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
 | ||||
| 
 | ||||
| package ethreg | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"math/big" | ||||
| 
 | ||||
| 	"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/registrar" | ||||
| 	"github.com/ethereum/go-ethereum/core" | ||||
| 	"github.com/ethereum/go-ethereum/core/state" | ||||
| 	"github.com/ethereum/go-ethereum/core/types" | ||||
| 	"github.com/ethereum/go-ethereum/core/vm" | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| 	"github.com/ethereum/go-ethereum/ethdb" | ||||
| 	"github.com/ethereum/go-ethereum/logger" | ||||
| 	"github.com/ethereum/go-ethereum/logger/glog" | ||||
| 	"github.com/ethereum/go-ethereum/params" | ||||
| ) | ||||
| 
 | ||||
| // registryAPIBackend is a backend for an Ethereum Registry.
 | ||||
| type registryAPIBackend struct { | ||||
| 	config  *params.ChainConfig | ||||
| 	bc      *core.BlockChain | ||||
| 	chainDb ethdb.Database | ||||
| 	txPool  *core.TxPool | ||||
| 	am      *accounts.Manager | ||||
| } | ||||
| 
 | ||||
| // PrivateRegistarAPI offers various functions to access the Ethereum registry.
 | ||||
| type PrivateRegistarAPI struct { | ||||
| 	config *params.ChainConfig | ||||
| 	be     *registryAPIBackend | ||||
| } | ||||
| 
 | ||||
| // NewPrivateRegistarAPI creates a new PrivateRegistarAPI instance.
 | ||||
| func NewPrivateRegistarAPI(config *params.ChainConfig, bc *core.BlockChain, chainDb ethdb.Database, txPool *core.TxPool, am *accounts.Manager) *PrivateRegistarAPI { | ||||
| 	return &PrivateRegistarAPI{ | ||||
| 		config: config, | ||||
| 		be: ®istryAPIBackend{ | ||||
| 			config:  config, | ||||
| 			bc:      bc, | ||||
| 			chainDb: chainDb, | ||||
| 			txPool:  txPool, | ||||
| 			am:      am, | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // SetGlobalRegistrar allows clients to set the global registry for the node.
 | ||||
| // This method can be used to deploy a new registry. First zero out the current
 | ||||
| // address by calling the method with namereg = '0x0' and then call this method
 | ||||
| // again with '' as namereg. This will submit a transaction to the network which
 | ||||
| // will deploy a new registry on execution. The TX hash is returned. When called
 | ||||
| // with namereg '' and the current address is not zero the current global is
 | ||||
| // address is returned..
 | ||||
| func (api *PrivateRegistarAPI) SetGlobalRegistrar(namereg string, from common.Address) (string, error) { | ||||
| 	return registrar.New(api.be).SetGlobalRegistrar(namereg, from) | ||||
| } | ||||
| 
 | ||||
| // SetHashReg queries the registry for a hash.
 | ||||
| func (api *PrivateRegistarAPI) SetHashReg(hashreg string, from common.Address) (string, error) { | ||||
| 	return registrar.New(api.be).SetHashReg(hashreg, from) | ||||
| } | ||||
| 
 | ||||
| // SetUrlHint queries the registry for an url.
 | ||||
| func (api *PrivateRegistarAPI) SetUrlHint(hashreg string, from common.Address) (string, error) { | ||||
| 	return registrar.New(api.be).SetUrlHint(hashreg, from) | ||||
| } | ||||
| 
 | ||||
| // SaveInfo stores contract information on the local file system.
 | ||||
| func (api *PrivateRegistarAPI) SaveInfo(info *compiler.ContractInfo, filename string) (contenthash common.Hash, err error) { | ||||
| 	return compiler.SaveInfo(info, filename) | ||||
| } | ||||
| 
 | ||||
| // Register registers a new content hash in the registry.
 | ||||
| func (api *PrivateRegistarAPI) Register(sender common.Address, addr common.Address, contentHashHex string) (bool, error) { | ||||
| 	block := api.be.bc.CurrentBlock() | ||||
| 	state, err := state.New(block.Root(), api.be.chainDb) | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 
 | ||||
| 	codeb := state.GetCode(addr) | ||||
| 	codeHash := common.BytesToHash(crypto.Keccak256(codeb)) | ||||
| 	contentHash := common.HexToHash(contentHashHex) | ||||
| 
 | ||||
| 	_, err = registrar.New(api.be).SetHashToHash(sender, codeHash, contentHash) | ||||
| 	return err == nil, err | ||||
| } | ||||
| 
 | ||||
| // RegisterUrl registers a new url in the registry.
 | ||||
| func (api *PrivateRegistarAPI) RegisterUrl(sender common.Address, contentHashHex string, url string) (bool, error) { | ||||
| 	_, err := registrar.New(api.be).SetUrlToHash(sender, common.HexToHash(contentHashHex), url) | ||||
| 	return err == nil, err | ||||
| } | ||||
| 
 | ||||
| // callmsg is the message type used for call transations.
 | ||||
| type callmsg struct { | ||||
| 	from          *state.StateObject | ||||
| 	to            *common.Address | ||||
| 	gas, gasPrice *big.Int | ||||
| 	value         *big.Int | ||||
| 	data          []byte | ||||
| } | ||||
| 
 | ||||
| // accessor boilerplate to implement core.Message
 | ||||
| func (m callmsg) From() (common.Address, error) { | ||||
| 	return m.from.Address(), nil | ||||
| } | ||||
| func (m callmsg) FromFrontier() (common.Address, error) { | ||||
| 	return m.from.Address(), nil | ||||
| } | ||||
| func (m callmsg) Nonce() uint64 { | ||||
| 	return 0 | ||||
| } | ||||
| func (m callmsg) CheckNonce() bool { | ||||
| 	return false | ||||
| } | ||||
| func (m callmsg) To() *common.Address { | ||||
| 	return m.to | ||||
| } | ||||
| func (m callmsg) GasPrice() *big.Int { | ||||
| 	return m.gasPrice | ||||
| } | ||||
| func (m callmsg) Gas() *big.Int { | ||||
| 	return m.gas | ||||
| } | ||||
| func (m callmsg) Value() *big.Int { | ||||
| 	return m.value | ||||
| } | ||||
| func (m callmsg) Data() []byte { | ||||
| 	return m.data | ||||
| } | ||||
| 
 | ||||
| // Call forms a transaction from the given arguments and tries to execute it on
 | ||||
| // a private VM with a copy of the state. Any changes are therefore only temporary
 | ||||
| // and not part of the actual state. This allows for local execution/queries.
 | ||||
| func (be *registryAPIBackend) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr string) (string, string, error) { | ||||
| 	block := be.bc.CurrentBlock() | ||||
| 	statedb, err := state.New(block.Root(), be.chainDb) | ||||
| 	if err != nil { | ||||
| 		return "", "", err | ||||
| 	} | ||||
| 
 | ||||
| 	var from *state.StateObject | ||||
| 	if len(fromStr) == 0 { | ||||
| 		accounts := be.am.Accounts() | ||||
| 		if len(accounts) == 0 { | ||||
| 			from = statedb.GetOrNewStateObject(common.Address{}) | ||||
| 		} else { | ||||
| 			from = statedb.GetOrNewStateObject(accounts[0].Address) | ||||
| 		} | ||||
| 	} else { | ||||
| 		from = statedb.GetOrNewStateObject(common.HexToAddress(fromStr)) | ||||
| 	} | ||||
| 
 | ||||
| 	from.SetBalance(common.MaxBig) | ||||
| 
 | ||||
| 	var to *common.Address | ||||
| 	if len(toStr) > 0 { | ||||
| 		addr := common.HexToAddress(toStr) | ||||
| 		to = &addr | ||||
| 	} | ||||
| 	gas := common.Big(gasStr) | ||||
| 	if gas.BitLen() == 0 { | ||||
| 		gas = big.NewInt(50000000) | ||||
| 	} | ||||
| 	gasPrice := common.Big(gasPriceStr) | ||||
| 	if gasPrice.BitLen() == 0 { | ||||
| 		gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon) | ||||
| 	} | ||||
| 	msg := types.NewMessage(from.Address(), to, 0, common.Big(valueStr), gas, gasPrice, common.FromHex(dataStr), false) | ||||
| 
 | ||||
| 	header := be.bc.CurrentBlock().Header() | ||||
| 	vmenv := core.NewEnv(statedb, be.config, be.bc, msg, header, vm.Config{}) | ||||
| 	gp := new(core.GasPool).AddGas(common.MaxBig) | ||||
| 	res, gas, err := core.ApplyMessage(vmenv, msg, gp) | ||||
| 
 | ||||
| 	return common.ToHex(res), gas.String(), err | ||||
| } | ||||
| 
 | ||||
| // StorageAt returns the data stores in the state for the given address and location.
 | ||||
| func (be *registryAPIBackend) StorageAt(addr string, storageAddr string) string { | ||||
| 	block := be.bc.CurrentBlock() | ||||
| 	state, err := state.New(block.Root(), be.chainDb) | ||||
| 	if err != nil { | ||||
| 		return "" | ||||
| 	} | ||||
| 	return state.GetState(common.HexToAddress(addr), common.HexToHash(storageAddr)).Hex() | ||||
| } | ||||
| 
 | ||||
| // Transact forms a transaction from the given arguments and submits it to the
 | ||||
| // transactio pool for execution.
 | ||||
| func (be *registryAPIBackend) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) { | ||||
| 	if len(toStr) > 0 && toStr != "0x" && !common.IsHexAddress(toStr) { | ||||
| 		return "", errors.New("invalid address") | ||||
| 	} | ||||
| 
 | ||||
| 	var ( | ||||
| 		from             = common.HexToAddress(fromStr) | ||||
| 		to               = common.HexToAddress(toStr) | ||||
| 		value            = common.Big(valueStr) | ||||
| 		gas              *big.Int | ||||
| 		price            *big.Int | ||||
| 		data             []byte | ||||
| 		contractCreation bool | ||||
| 	) | ||||
| 
 | ||||
| 	if len(gasStr) == 0 { | ||||
| 		gas = big.NewInt(90000) | ||||
| 	} else { | ||||
| 		gas = common.Big(gasStr) | ||||
| 	} | ||||
| 
 | ||||
| 	if len(gasPriceStr) == 0 { | ||||
| 		price = big.NewInt(10000000000000) | ||||
| 	} else { | ||||
| 		price = common.Big(gasPriceStr) | ||||
| 	} | ||||
| 
 | ||||
| 	data = common.FromHex(codeStr) | ||||
| 	if len(toStr) == 0 { | ||||
| 		contractCreation = true | ||||
| 	} | ||||
| 
 | ||||
| 	nonce := be.txPool.State().GetNonce(from) | ||||
| 	if len(nonceStr) != 0 { | ||||
| 		nonce = common.Big(nonceStr).Uint64() | ||||
| 	} | ||||
| 
 | ||||
| 	var tx *types.Transaction | ||||
| 	if contractCreation { | ||||
| 		tx = types.NewContractCreation(nonce, value, gas, price, data) | ||||
| 	} else { | ||||
| 		tx = types.NewTransaction(nonce, to, value, gas, price, data) | ||||
| 	} | ||||
| 
 | ||||
| 	sigHash := (types.HomesteadSigner{}).Hash(tx) | ||||
| 	signature, err := be.am.SignEthereum(from, sigHash.Bytes()) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	signedTx, err := tx.WithSignature(types.HomesteadSigner{}, signature) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 
 | ||||
| 	be.txPool.SetLocal(signedTx) | ||||
| 	if err := be.txPool.Add(signedTx); err != nil { | ||||
| 		return "", nil | ||||
| 	} | ||||
| 
 | ||||
| 	if contractCreation { | ||||
| 		addr := crypto.CreateAddress(from, nonce) | ||||
| 		glog.V(logger.Info).Infof("Tx(%s) created: %s\n", signedTx.Hash().Hex(), addr.Hex()) | ||||
| 	} else { | ||||
| 		glog.V(logger.Info).Infof("Tx(%s) to: %s\n", signedTx.Hash().Hex(), tx.To().Hex()) | ||||
| 	} | ||||
| 
 | ||||
| 	return signedTx.Hash().Hex(), nil | ||||
| } | ||||
| @ -1,436 +0,0 @@ | ||||
| // Copyright 2015 The go-ethereum Authors
 | ||||
| // This file is part of the go-ethereum library.
 | ||||
| //
 | ||||
| // The go-ethereum library is free software: you can redistribute it and/or modify
 | ||||
| // it under the terms of the GNU Lesser General Public License as published by
 | ||||
| // the Free Software Foundation, either version 3 of the License, or
 | ||||
| // (at your option) any later version.
 | ||||
| //
 | ||||
| // The go-ethereum library is distributed in the hope that it will be useful,
 | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | ||||
| // GNU Lesser General Public License for more details.
 | ||||
| //
 | ||||
| // You should have received a copy of the GNU Lesser General Public License
 | ||||
| // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
 | ||||
| 
 | ||||
| package 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 the first time any Registrar method is called | ||||
| in a client session. | ||||
| This is done for frontier by default, otherwise the caller needs to make sure | ||||
| the relevant environment initialised the desired contracts | ||||
| */ | ||||
| var ( | ||||
| 	// GlobalRegistrarAddr = "0xc6d9d2cd449a754c494264e1809c50e34d64562b" // olympic
 | ||||
| 	GlobalRegistrarAddr = "0x33990122638b9132ca29c723bdf037f1a891a70c" // frontier
 | ||||
| 	HashRegAddr         = "0x23bf622b5a65f6060d855fca401133ded3520620" // frontier
 | ||||
| 	UrlHintAddr         = "0x73ed5ef6c010727dfd2671dbb70faac19ec18626" // frontier
 | ||||
| 
 | ||||
| 	zero = regexp.MustCompile("^(0x)?0*$") | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	trueHex  = "0000000000000000000000000000000000000000000000000000000000000001" | ||||
| 	falseHex = "0000000000000000000000000000000000000000000000000000000000000000" | ||||
| ) | ||||
| 
 | ||||
| func abiSignature(s string) string { | ||||
| 	return common.ToHex(crypto.Keccak256([]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 zero.MatchString(GlobalRegistrarAddr) { | ||||
| 		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) { | ||||
| 	if zero.MatchString(GlobalRegistrarAddr) { | ||||
| 		return "", fmt.Errorf("GlobalRegistrar address is not set") | ||||
| 	} | ||||
| 	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) { | ||||
| 	if zero.MatchString(GlobalRegistrarAddr) { | ||||
| 		return "", fmt.Errorf("GlobalRegistrar address is not set") | ||||
| 	} | ||||
| 
 | ||||
| 	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) { | ||||
| 	if zero.MatchString(GlobalRegistrarAddr) { | ||||
| 		return address, fmt.Errorf("GlobalRegistrar address is not set") | ||||
| 	} | ||||
| 
 | ||||
| 	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) { | ||||
| 	if zero.MatchString(HashRegAddr) { | ||||
| 		return "", fmt.Errorf("HashReg address is not set") | ||||
| 	} | ||||
| 	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) { | ||||
| 	if zero.MatchString(HashRegAddr) { | ||||
| 		return "", fmt.Errorf("HashReg address is not set") | ||||
| 	} | ||||
| 
 | ||||
| 	_, 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) { | ||||
| 	if zero.MatchString(UrlHintAddr) { | ||||
| 		return "", fmt.Errorf("UrlHint address is not set") | ||||
| 	} | ||||
| 
 | ||||
| 	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) { | ||||
| 	if zero.MatchString(HashRegAddr) { | ||||
| 		return common.Hash{}, fmt.Errorf("HashReg address is not set") | ||||
| 	} | ||||
| 
 | ||||
| 	// 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("HashToHash: 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) { | ||||
| 	if zero.MatchString(UrlHintAddr) { | ||||
| 		return "", fmt.Errorf("UrlHint address is not set") | ||||
| 	} | ||||
| 	// 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("HashToUrl: 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.Keccak256(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):], "" | ||||
| } | ||||
| @ -1,158 +0,0 @@ | ||||
| // Copyright 2015 The go-ethereum Authors
 | ||||
| // This file is part of the go-ethereum library.
 | ||||
| //
 | ||||
| // The go-ethereum library is free software: you can redistribute it and/or modify
 | ||||
| // it under the terms of the GNU Lesser General Public License as published by
 | ||||
| // the Free Software Foundation, either version 3 of the License, or
 | ||||
| // (at your option) any later version.
 | ||||
| //
 | ||||
| // The go-ethereum library is distributed in the hope that it will be useful,
 | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | ||||
| // GNU Lesser General Public License for more details.
 | ||||
| //
 | ||||
| // You should have received a copy of the GNU Lesser General Public License
 | ||||
| // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
 | ||||
| 
 | ||||
| package registrar | ||||
| 
 | ||||
| import ( | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/ethereum/go-ethereum/common" | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| ) | ||||
| 
 | ||||
| type testBackend struct { | ||||
| 	// contracts mock
 | ||||
| 	contracts map[string](map[string]string) | ||||
| } | ||||
| 
 | ||||
| var ( | ||||
| 	text     = "test" | ||||
| 	codehash = common.StringToHash("1234") | ||||
| 	hash     = common.BytesToHash(crypto.Keccak256([]byte(text))) | ||||
| 	url      = "bzz://bzzhash/my/path/contr.act" | ||||
| ) | ||||
| 
 | ||||
| func NewTestBackend() *testBackend { | ||||
| 	self := &testBackend{} | ||||
| 	self.contracts = make(map[string](map[string]string)) | ||||
| 	return self | ||||
| } | ||||
| 
 | ||||
| func (self *testBackend) initHashReg() { | ||||
| 	self.contracts[HashRegAddr[2:]] = make(map[string]string) | ||||
| 	key := storageAddress(storageMapping(storageIdx2Addr(1), codehash[:])) | ||||
| 	self.contracts[HashRegAddr[2:]][key] = hash.Hex() | ||||
| } | ||||
| 
 | ||||
| func (self *testBackend) initUrlHint() { | ||||
| 	self.contracts[UrlHintAddr[2:]] = make(map[string]string) | ||||
| 	mapaddr := storageMapping(storageIdx2Addr(1), hash[:]) | ||||
| 
 | ||||
| 	key := storageAddress(storageFixedArray(mapaddr, storageIdx2Addr(0))) | ||||
| 	self.contracts[UrlHintAddr[2:]][key] = common.ToHex([]byte(url)) | ||||
| 	key = storageAddress(storageFixedArray(mapaddr, storageIdx2Addr(1))) | ||||
| 	self.contracts[UrlHintAddr[2:]][key] = "0x0" | ||||
| } | ||||
| 
 | ||||
| func (self *testBackend) StorageAt(ca, sa string) (res string) { | ||||
| 	c := self.contracts[ca] | ||||
| 	if c == nil { | ||||
| 		return "0x0" | ||||
| 	} | ||||
| 	res = c[sa] | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (self *testBackend) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) { | ||||
| 	return "", nil | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| 	_, err := res.SetGlobalRegistrar("addresshex", common.BigToAddress(common.Big1)) | ||||
| 	if err != nil { | ||||
| 		t.Errorf("unexpected error: %v'", err) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestHashToHash(t *testing.T) { | ||||
| 	b := NewTestBackend() | ||||
| 	res := New(b) | ||||
| 
 | ||||
| 	HashRegAddr = "0x0" | ||||
| 	got, err := res.HashToHash(codehash) | ||||
| 	if err == nil { | ||||
| 		t.Errorf("expected error") | ||||
| 	} else { | ||||
| 		exp := "HashReg address is not set" | ||||
| 		if err.Error() != exp { | ||||
| 			t.Errorf("incorrect error, expected '%v', got '%v'", exp, err.Error()) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	HashRegAddr = common.BigToAddress(common.Big1).Hex() //[2:]
 | ||||
| 	got, err = res.HashToHash(codehash) | ||||
| 	if err == nil { | ||||
| 		t.Errorf("expected error") | ||||
| 	} else { | ||||
| 		exp := "HashToHash: content hash not found for '" + codehash.Hex() + "'" | ||||
| 		if err.Error() != exp { | ||||
| 			t.Errorf("incorrect error, expected '%v', got '%v'", exp, err.Error()) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	b.initHashReg() | ||||
| 	got, err = res.HashToHash(codehash) | ||||
| 	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()) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestHashToUrl(t *testing.T) { | ||||
| 	b := NewTestBackend() | ||||
| 	res := New(b) | ||||
| 
 | ||||
| 	UrlHintAddr = "0x0" | ||||
| 	got, err := res.HashToUrl(hash) | ||||
| 	if err == nil { | ||||
| 		t.Errorf("expected error") | ||||
| 	} else { | ||||
| 		exp := "UrlHint address is not set" | ||||
| 		if err.Error() != exp { | ||||
| 			t.Errorf("incorrect error, expected '%v', got '%v'", exp, err.Error()) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	UrlHintAddr = common.BigToAddress(common.Big2).Hex() //[2:]
 | ||||
| 	got, err = res.HashToUrl(hash) | ||||
| 	if err == nil { | ||||
| 		t.Errorf("expected error") | ||||
| 	} else { | ||||
| 		exp := "HashToUrl: URL hint not found for '" + hash.Hex() + "'" | ||||
| 		if err.Error() != exp { | ||||
| 			t.Errorf("incorrect error, expected '%v', got '%v'", exp, err.Error()) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	b.initUrlHint() | ||||
| 	got, err = res.HashToUrl(hash) | ||||
| 	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) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @ -31,8 +31,6 @@ import ( | ||||
| 	"github.com/ethereum/ethash" | ||||
| 	"github.com/ethereum/go-ethereum/accounts" | ||||
| 	"github.com/ethereum/go-ethereum/common" | ||||
| 	"github.com/ethereum/go-ethereum/common/httpclient" | ||||
| 	"github.com/ethereum/go-ethereum/common/registrar/ethreg" | ||||
| 	"github.com/ethereum/go-ethereum/core" | ||||
| 	"github.com/ethereum/go-ethereum/core/types" | ||||
| 	"github.com/ethereum/go-ethereum/eth/downloader" | ||||
| @ -127,7 +125,6 @@ type Ethereum struct { | ||||
| 
 | ||||
| 	eventMux       *event.TypeMux | ||||
| 	pow            *ethash.Ethash | ||||
| 	httpclient     *httpclient.HTTPClient | ||||
| 	accountManager *accounts.Manager | ||||
| 
 | ||||
| 	ApiBackend *EthApiBackend | ||||
| @ -173,7 +170,6 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { | ||||
| 		pow:            pow, | ||||
| 		shutdownChan:   make(chan bool), | ||||
| 		stopDbUpgrade:  stopDbUpgrade, | ||||
| 		httpclient:     httpclient.New(config.DocRoot), | ||||
| 		netVersionId:   config.NetworkId, | ||||
| 		NatSpec:        config.NatSpec, | ||||
| 		PowTest:        config.PowTest, | ||||
| @ -356,10 +352,6 @@ func (s *Ethereum) APIs() []rpc.API { | ||||
| 			Version:   "1.0", | ||||
| 			Service:   s.netRPCService, | ||||
| 			Public:    true, | ||||
| 		}, { | ||||
| 			Namespace: "admin", | ||||
| 			Version:   "1.0", | ||||
| 			Service:   ethreg.NewPrivateRegistarAPI(s.chainConfig, s.blockchain, s.chainDb, s.txPool, s.accountManager), | ||||
| 		}, | ||||
| 	}...) | ||||
| } | ||||
| @ -527,12 +519,6 @@ 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 | ||||
| } | ||||
| 
 | ||||
| // dagFiles(epoch) returns the two alternative DAG filenames (not a path)
 | ||||
| // 1) <revision>-<hex(seedhash[8])> 2) full-R<revision>-<hex(seedhash[8])>
 | ||||
| func dagFiles(epoch uint64) (string, string) { | ||||
|  | ||||
| @ -226,41 +226,6 @@ web3._extend({ | ||||
| 		new web3._extend.Method({ | ||||
| 			name: 'stopWS', | ||||
| 			call: 'admin_stopWS' | ||||
| 		}), | ||||
| 		new web3._extend.Method({ | ||||
| 			name: 'setGlobalRegistrar', | ||||
| 			call: 'admin_setGlobalRegistrar', | ||||
| 			params: 2 | ||||
| 		}), | ||||
| 		new web3._extend.Method({ | ||||
| 			name: 'setHashReg', | ||||
| 			call: 'admin_setHashReg', | ||||
| 			params: 2 | ||||
| 		}), | ||||
| 		new web3._extend.Method({ | ||||
| 			name: 'setUrlHint', | ||||
| 			call: 'admin_setUrlHint', | ||||
| 			params: 2 | ||||
| 		}), | ||||
| 		new web3._extend.Method({ | ||||
| 			name: 'saveInfo', | ||||
| 			call: 'admin_saveInfo', | ||||
| 			params: 2 | ||||
| 		}), | ||||
| 		new web3._extend.Method({ | ||||
| 			name: 'register', | ||||
| 			call: 'admin_register', | ||||
| 			params: 3 | ||||
| 		}), | ||||
| 		new web3._extend.Method({ | ||||
| 			name: 'registerUrl', | ||||
| 			call: 'admin_registerUrl', | ||||
| 			params: 3 | ||||
| 		}), | ||||
| 		new web3._extend.Method({ | ||||
| 			name: 'httpGet', | ||||
| 			call: 'admin_httpGet', | ||||
| 			params: 2 | ||||
| 		}) | ||||
| 	], | ||||
| 	properties: | ||||
|  | ||||
| @ -26,7 +26,6 @@ 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/types" | ||||
| 	"github.com/ethereum/go-ethereum/eth" | ||||
| @ -62,7 +61,6 @@ type LightEthereum struct { | ||||
| 
 | ||||
| 	eventMux       *event.TypeMux | ||||
| 	pow            *ethash.Ethash | ||||
| 	httpclient     *httpclient.HTTPClient | ||||
| 	accountManager *accounts.Manager | ||||
| 	solcPath       string | ||||
| 	solc           *compiler.Solidity | ||||
| @ -96,7 +94,6 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) { | ||||
| 		accountManager: ctx.AccountManager, | ||||
| 		pow:            pow, | ||||
| 		shutdownChan:   make(chan bool), | ||||
| 		httpclient:     httpclient.New(config.DocRoot), | ||||
| 		netVersionId:   config.NetworkId, | ||||
| 		NatSpec:        config.NatSpec, | ||||
| 		PowTest:        config.PowTest, | ||||
|  | ||||
| @ -22,8 +22,6 @@ import ( | ||||
| 	"strings" | ||||
| 	"testing" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/ethereum/go-ethereum/common/httpclient" | ||||
| ) | ||||
| 
 | ||||
| const port = "3222" | ||||
| @ -41,10 +39,10 @@ func TestRoundTripper(t *testing.T) { | ||||
| 	go http.ListenAndServe(":"+port, serveMux) | ||||
| 
 | ||||
| 	rt := &RoundTripper{Port: port} | ||||
| 	client := httpclient.New("/") | ||||
| 	client.RegisterProtocol("bzz", rt) | ||||
| 
 | ||||
| 	resp, err := client.Client().Get("bzz://test.com/path") | ||||
| 	trans := &http.Transport{} | ||||
| 	trans.RegisterProtocol("bzz", rt) | ||||
| 	client := &http.Client{Transport: trans} | ||||
| 	resp, err := client.Get("bzz://test.com/path") | ||||
| 	if err != nil { | ||||
| 		t.Errorf("expected no error, got %v", err) | ||||
| 		return | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user