Merge pull request #3346 from obscuren/registrar-removal

common/registrar, eth: removed registrar (tech debt)
This commit is contained in:
Péter Szilágyi 2016-11-25 14:22:53 +02:00 committed by GitHub
commit 9c3ea0d32d
11 changed files with 5 additions and 1296 deletions

View File

@ -373,7 +373,7 @@ var (
// ATM the url is left to the user and deployment to // ATM the url is left to the user and deployment to
JSpathFlag = cli.StringFlag{ JSpathFlag = cli.StringFlag{
Name: "jspath", Name: "jspath",
Usage: "JavaScript root path for `loadScript` and document root for `admin.httpGet`", Usage: "JavaScript root path for `loadScript`",
Value: ".", Value: ".",
} }
SolcPathFlag = cli.StringFlag{ SolcPathFlag = cli.StringFlag{

View File

@ -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
}

View File

@ -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

View File

@ -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: &registryAPIBackend{
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
}

View File

@ -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):], ""
}

View File

@ -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)
}
}
}

View File

@ -31,8 +31,6 @@ import (
"github.com/ethereum/ethash" "github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common" "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"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
@ -127,7 +125,6 @@ type Ethereum struct {
eventMux *event.TypeMux eventMux *event.TypeMux
pow *ethash.Ethash pow *ethash.Ethash
httpclient *httpclient.HTTPClient
accountManager *accounts.Manager accountManager *accounts.Manager
ApiBackend *EthApiBackend ApiBackend *EthApiBackend
@ -173,7 +170,6 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
pow: pow, pow: pow,
shutdownChan: make(chan bool), shutdownChan: make(chan bool),
stopDbUpgrade: stopDbUpgrade, stopDbUpgrade: stopDbUpgrade,
httpclient: httpclient.New(config.DocRoot),
netVersionId: config.NetworkId, netVersionId: config.NetworkId,
NatSpec: config.NatSpec, NatSpec: config.NatSpec,
PowTest: config.PowTest, PowTest: config.PowTest,
@ -356,10 +352,6 @@ func (s *Ethereum) APIs() []rpc.API {
Version: "1.0", Version: "1.0",
Service: s.netRPCService, Service: s.netRPCService,
Public: true, 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) 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) // dagFiles(epoch) returns the two alternative DAG filenames (not a path)
// 1) <revision>-<hex(seedhash[8])> 2) full-R<revision>-<hex(seedhash[8])> // 1) <revision>-<hex(seedhash[8])> 2) full-R<revision>-<hex(seedhash[8])>
func dagFiles(epoch uint64) (string, string) { func dagFiles(epoch uint64) (string, string) {

View File

@ -226,41 +226,6 @@ web3._extend({
new web3._extend.Method({ new web3._extend.Method({
name: 'stopWS', name: 'stopWS',
call: 'admin_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: properties:

View File

@ -26,7 +26,6 @@ import (
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/compiler" "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"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
@ -62,7 +61,6 @@ type LightEthereum struct {
eventMux *event.TypeMux eventMux *event.TypeMux
pow *ethash.Ethash pow *ethash.Ethash
httpclient *httpclient.HTTPClient
accountManager *accounts.Manager accountManager *accounts.Manager
solcPath string solcPath string
solc *compiler.Solidity solc *compiler.Solidity
@ -96,7 +94,6 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
accountManager: ctx.AccountManager, accountManager: ctx.AccountManager,
pow: pow, pow: pow,
shutdownChan: make(chan bool), shutdownChan: make(chan bool),
httpclient: httpclient.New(config.DocRoot),
netVersionId: config.NetworkId, netVersionId: config.NetworkId,
NatSpec: config.NatSpec, NatSpec: config.NatSpec,
PowTest: config.PowTest, PowTest: config.PowTest,

View File

@ -22,8 +22,6 @@ import (
"strings" "strings"
"testing" "testing"
"time" "time"
"github.com/ethereum/go-ethereum/common/httpclient"
) )
const port = "3222" const port = "3222"
@ -41,10 +39,10 @@ func TestRoundTripper(t *testing.T) {
go http.ListenAndServe(":"+port, serveMux) go http.ListenAndServe(":"+port, serveMux)
rt := &RoundTripper{Port: port} rt := &RoundTripper{Port: port}
client := httpclient.New("/") trans := &http.Transport{}
client.RegisterProtocol("bzz", rt) trans.RegisterProtocol("bzz", rt)
client := &http.Client{Transport: trans}
resp, err := client.Client().Get("bzz://test.com/path") resp, err := client.Get("bzz://test.com/path")
if err != nil { if err != nil {
t.Errorf("expected no error, got %v", err) t.Errorf("expected no error, got %v", err)
return return