common/registrar: delete the old registrar code
The registrar was broken, unmaintained and there is a much better replacement: ENS. (cherry picked from commit 6ca8f57b08d550613175260cab7633adcacbe6ab)
This commit is contained in:
parent
01d5fc670b
commit
18d51d1de8
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -32,7 +32,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/httpclient"
|
"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 +126,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 +171,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 +353,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),
|
|
||||||
},
|
},
|
||||||
}...)
|
}...)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user