* lines with leading space are ommitted from history
* exit processed even with whitespace around
* all whitespace lines (not only empty ones) are ignored

add 7 missing commands to admin api autocomplete

registrar: methods now return proper error if reg addresses are not set. fixes #1457

rpc/console: fix personal.newAccount() regression. Now all comms accept interactive password

registrar: add registrar tests for errors

crypto: catch AES decryption error on presale wallet import + fix error msg format. fixes #1580

CLI: improve error message when starting a second instance of geth. fixes #1564

cli/accounts: unlock multiple accounts. fixes #1785
* make unlocking multiple accounts work with inline <() fd
* passwdfile now correctly read only once
* improve logs
* fix CLI help text for unlocking

fix regression with docRoot / admin API
* docRoot/jspath passed to rpc/api ParseApis, which passes onto adminApi
* docRoot field for JS console in order to pass when RPC is (re)started
* improve flag desc for jspath

common/docserver: catch http errors from response

fix rpc/api tests

common/natspec: fix end to end test (skipped because takes 8s)

registrar: fix major regression:
* deploy registrars on frontier
* register HashsReg and UrlHint in GlobalRegistrar.
* set all 3 contract addresses in code
* zero out addresses first in tests
This commit is contained in:
zelig
2015-09-22 10:34:58 +02:00
parent 58d0752fdd
commit 8b81ad1fc4
18 changed files with 352 additions and 156 deletions

View File

@ -95,14 +95,20 @@ func (self *DocServer) Get(uri, path string) (content []byte, err error) {
resp.Body.Close()
}
}()
if err != nil {
return
}
content, err = ioutil.ReadAll(resp.Body)
if err != nil {
return
}
if resp.StatusCode/100 != 2 {
return content, fmt.Errorf("HTTP error: %s", resp.Status)
}
if path != "" {
var abspath string
abspath, err = filepath.Abs(path)

View File

@ -21,8 +21,8 @@ import (
"io/ioutil"
"math/big"
"os"
"path/filepath"
"runtime"
"strings"
"testing"
"time"
@ -38,7 +38,9 @@ import (
)
const (
testAddress = "0x8605cdbbdb6d264aa742e77020dcbc58fcdce182"
testBalance = "10000000000000000000"
testKey = "e6fab74a43941f82d89cb7faa408e227cdad3153c4720e540e855c19b15e6674"
testFileName = "long_file_name_for_testing_registration_of_URLs_longer_than_32_bytes.content"
@ -48,7 +50,7 @@ const (
testExpNotice2 = `About to submit transaction (NatSpec notice error: abi key does not match any method): {"params":[{"to":"%s","data": "0x31e12c20"}]}`
testExpNotice3 = `About to submit transaction (no NatSpec info found for contract: content hash not found for '0x1392c62d05b2d149e22a339c531157ae06b44d39a674cce500064b12b9aeb019'): {"params":[{"to":"%s","data": "0x300a3bbfb3a2dea218de5d8bbe6c4645aadbf67b5ab00ecb1a9ec95dbdad6a0eed3e41a7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066696c653a2f2f2f746573742e636f6e74656e74"}]}`
testExpNotice3 = `About to submit transaction (no NatSpec info found for contract: HashToHash: content hash not found for '0x1392c62d05b2d149e22a339c531157ae06b44d39a674cce500064b12b9aeb019'): {"params":[{"to":"%s","data": "0x300a3bbfb3a2dea218de5d8bbe6c4645aadbf67b5ab00ecb1a9ec95dbdad6a0eed3e41a7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066696c653a2f2f2f746573742e636f6e74656e74"}]}`
)
const (
@ -100,6 +102,10 @@ type testFrontend struct {
wantNatSpec bool
}
func (self *testFrontend) AskPassword() (string, bool) {
return "", true
}
func (self *testFrontend) UnlockAccount(acc []byte) bool {
self.ethereum.AccountManager().Unlock(common.BytesToAddress(acc), "password")
return true
@ -115,42 +121,42 @@ func (self *testFrontend) ConfirmTransaction(tx string) bool {
func testEth(t *testing.T) (ethereum *eth.Ethereum, err error) {
os.RemoveAll("/tmp/eth-natspec/")
err = os.MkdirAll("/tmp/eth-natspec/keystore", os.ModePerm)
tmp, err := ioutil.TempDir("", "natspec-test")
if err != nil {
panic(err)
t.Fatal(err)
}
// create a testAddress
ks := crypto.NewKeyStorePassphrase("/tmp/eth-natspec/keystore")
am := accounts.NewManager(ks)
testAccount, err := am.NewAccount("password")
if err != nil {
panic(err)
}
testAddress := strings.TrimPrefix(testAccount.Address.Hex(), "0x")
db, _ := ethdb.NewMemDatabase()
// set up mock genesis with balance on the testAddress
core.WriteGenesisBlockForTesting(db, core.GenesisAccount{common.HexToAddress(testAddress), common.String2Big(testBalance)})
addr := common.HexToAddress(testAddress)
core.WriteGenesisBlockForTesting(db, core.GenesisAccount{addr, common.String2Big(testBalance)})
ks := crypto.NewKeyStorePassphrase(filepath.Join(tmp, "keystore"))
am := accounts.NewManager(ks)
keyb, err := crypto.HexToECDSA(testKey)
if err != nil {
t.Fatal(err)
}
key := crypto.NewKeyFromECDSA(keyb)
err = ks.StoreKey(key, "")
if err != nil {
t.Fatal(err)
}
err = am.Unlock(key.Address, "")
if err != nil {
t.Fatal(err)
}
// only use minimalistic stack with no networking
ethereum, err = eth.New(&eth.Config{
DataDir: "/tmp/eth-natspec",
AccountManager: am,
MaxPeers: 0,
PowTest: true,
Etherbase: common.HexToAddress(testAddress),
NewDB: func(path string) (ethdb.Database, error) { return db, nil },
return eth.New(&eth.Config{
DataDir: tmp,
AccountManager: am,
Etherbase: common.HexToAddress(testAddress),
MaxPeers: 0,
PowTest: true,
NewDB: func(path string) (ethdb.Database, error) { return db, nil },
GpoMinGasPrice: common.Big1,
GpobaseCorrectionFactor: 1,
GpoMaxGasPrice: common.Big1,
})
if err != nil {
panic(err)
}
return
}
func testInit(t *testing.T) (self *testFrontend) {
@ -174,36 +180,49 @@ func testInit(t *testing.T) (self *testFrontend) {
// initialise the registry contracts
reg := registrar.New(self.xeth)
var registrarTxhash, hashRegTxhash, urlHintTxhash string
registrarTxhash, err = reg.SetGlobalRegistrar("", addr)
if err != nil {
t.Errorf("error creating GlobalRegistrar: %v", err)
}
registrar.GlobalRegistrarAddr = "0x0"
hashRegTxhash, err = reg.SetHashReg("", addr)
var txG, txH, txU string
txG, err = reg.SetGlobalRegistrar("", addr)
if err != nil {
t.Fatalf("error creating GlobalRegistrar: %v", err)
}
if !processTxs(self, t, 1) {
t.Fatalf("error mining txs")
}
recG := self.xeth.GetTxReceipt(common.HexToHash(txG))
if recG == nil {
t.Fatalf("blockchain error creating GlobalRegistrar")
}
registrar.GlobalRegistrarAddr = recG.ContractAddress.Hex()
txH, err = reg.SetHashReg("", addr)
if err != nil {
t.Errorf("error creating HashReg: %v", err)
}
urlHintTxhash, err = reg.SetUrlHint("", addr)
if !processTxs(self, t, 1) {
t.Errorf("error mining txs")
}
recH := self.xeth.GetTxReceipt(common.HexToHash(txH))
if recH == nil {
t.Fatalf("blockchain error creating HashReg")
}
registrar.HashRegAddr = recH.ContractAddress.Hex()
txU, err = reg.SetUrlHint("", addr)
if err != nil {
t.Errorf("error creating UrlHint: %v", err)
}
if !processTxs(self, t, 3) {
if !processTxs(self, t, 1) {
t.Errorf("error mining txs")
}
_ = registrarTxhash
_ = hashRegTxhash
_ = urlHintTxhash
/* TODO:
* lookup receipt and contract addresses by tx hash
* name registration for HashReg and UrlHint addresses
* mine those transactions
* then set once more SetHashReg SetUrlHint
*/
recU := self.xeth.GetTxReceipt(common.HexToHash(txU))
if recU == nil {
t.Fatalf("blockchain error creating UrlHint")
}
registrar.UrlHintAddr = recU.ContractAddress.Hex()
return
}
// end to end test
@ -215,7 +234,7 @@ func TestNatspecE2E(t *testing.T) {
addr, _ := tf.ethereum.Etherbase()
// create a contractInfo file (mock cloud-deployed contract metadocs)
// incidentally this is the info for the registry contract itself
// incidentally this is the info for the HashReg contract itself
ioutil.WriteFile("/tmp/"+testFileName, []byte(testContractInfo), os.ModePerm)
dochash := crypto.Sha3Hash([]byte(testContractInfo))
@ -223,10 +242,6 @@ func TestNatspecE2E(t *testing.T) {
codeb := tf.xeth.CodeAtBytes(registrar.HashRegAddr)
codehash := crypto.Sha3Hash(codeb)
// use resolver to register codehash->dochash->url
// test if globalregistry works
// registrar.HashRefAddr = "0x0"
// registrar.UrlHintAddr = "0x0"
reg := registrar.New(tf.xeth)
_, err := reg.SetHashToHash(addr, codehash, dochash)
if err != nil {

View File

@ -48,17 +48,16 @@ The Registrar uses 3 contracts on the blockchain:
These contracts are (currently) not included in the genesis block.
Each Set<X> needs to be called once on each blockchain/network once.
Contract addresses need to be set (HashReg and UrlHint retrieved from the global
registrar the first time any Registrar method is called in a client session
So the caller needs to make sure the relevant environment initialised the desired
contracts
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 (
UrlHintAddr = "0x0"
HashRegAddr = "0x0"
GlobalRegistrarAddr = "0x0"
// GlobalRegistrarAddr = "0xc6d9d2cd449a754c494264e1809c50e34d64562b"
// GlobalRegistrarAddr = "0xc6d9d2cd449a754c494264e1809c50e34d64562b" // olympic
GlobalRegistrarAddr = "0x33990122638b9132ca29c723bdf037f1a891a70c" // frontier
HashRegAddr = "0x23bf622b5a65f6060d855fca401133ded3520620" // frontier
UrlHintAddr = "0x73ed5ef6c010727dfd2671dbb70faac19ec18626" // frontier
zero = regexp.MustCompile("^(0x)?0*$")
)
@ -113,7 +112,7 @@ func (self *Registrar) SetGlobalRegistrar(namereg string, addr common.Address) (
GlobalRegistrarAddr = namereg
return
}
if GlobalRegistrarAddr == "0x0" || GlobalRegistrarAddr == "0x" {
if zero.MatchString(GlobalRegistrarAddr) {
if (addr == common.Address{}) {
err = fmt.Errorf("GlobalRegistrar address not found and sender for creation not given")
return
@ -200,6 +199,9 @@ func (self *Registrar) SetUrlHint(urlhint string, addr common.Address) (txhash s
// 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)
@ -215,6 +217,10 @@ func (self *Registrar) ReserveName(address common.Address, name string) (txh str
// 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)
@ -231,6 +237,10 @@ func (self *Registrar) SetAddressToName(from common.Address, name string, addres
// 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)
@ -249,6 +259,9 @@ func (self *Registrar) NameToAddr(from common.Address, name string) (address com
// 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,
@ -261,6 +274,10 @@ func (self *Registrar) SetOwner(address common.Address) (txh string, err error)
// 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
@ -284,6 +301,10 @@ func (self *Registrar) SetHashToHash(address common.Address, codehash, dochash c
// 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)
@ -321,13 +342,17 @@ func (self *Registrar) SetUrlToHash(address common.Address, hash common.Hash, ur
// 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("content hash not found for '%v'", khash.Hex())
err = fmt.Errorf("HashToHash: content hash not found for '%v'", khash.Hex())
return
}
copy(chash[:], common.Hex2BytesFixed(hash[2:], 32))
@ -339,6 +364,9 @@ func (self *Registrar) HashToHash(khash common.Hash) (chash common.Hash, err err
// 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
@ -358,7 +386,7 @@ func (self *Registrar) HashToUrl(chash common.Hash) (uri string, err error) {
}
if len(uri) == 0 {
err = fmt.Errorf("GetURLhint: URL hint not found for '%v'", chash.Hex())
err = fmt.Errorf("HashToUrl: URL hint not found for '%v'", chash.Hex())
}
return
}

View File

@ -36,29 +36,31 @@ var (
)
func NewTestBackend() *testBackend {
HashRegAddr = common.BigToAddress(common.Big0).Hex() //[2:]
UrlHintAddr = common.BigToAddress(common.Big1).Hex() //[2:]
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)))
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"
return self
}
func (self *testBackend) StorageAt(ca, sa string) (res string) {
c := self.contracts[ca]
if c == nil {
return
return "0x0"
}
res = c[sa]
return
@ -84,9 +86,31 @@ func TestSetGlobalRegistrar(t *testing.T) {
func TestHashToHash(t *testing.T) {
b := NewTestBackend()
res := New(b)
// res.SetHashReg()
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 {
@ -99,11 +123,33 @@ func TestHashToHash(t *testing.T) {
func TestHashToUrl(t *testing.T) {
b := NewTestBackend()
res := New(b)
// res.SetUrlHint()
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 error, got %v", err)
t.Errorf("expected no error, got %v", err)
} else {
if got != url {
t.Errorf("incorrect result, expected '%v', got '%s'", url, got)