func (self *EthReg) Resolver(n *big.Int) *registrar.Registrar { xe := self.backend if n != nil { xe = self.backend.AtStateNum(n.Int64()) } return registrar.New(xe) }
func testInit(t *testing.T) (self *testFrontend) { // initialise and start minimal ethereum stack ethereum, err := testEth(t) if err != nil { t.Errorf("error creating ethereum: %v", err) return } err = ethereum.Start() if err != nil { t.Errorf("error starting ethereum: %v", err) return } // mock frontend self = &testFrontend{t: t, ethereum: ethereum} self.xeth = xe.New(ethereum, self) self.wait = self.xeth.UpdateState() addr, _ := self.ethereum.Etherbase() // 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) } hashRegTxhash, err = reg.SetHashReg("", addr) if err != nil { t.Errorf("error creating HashReg: %v", err) } urlHintTxhash, err = reg.SetUrlHint("", addr) if err != nil { t.Errorf("error creating UrlHint: %v", err) } if !processTxs(self, t, 3) { 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 */ return }
// 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 }
func (self *adminApi) RegisterUrl(req *shared.Request) (interface{}, error) { args := new(RegisterUrlArgs) if err := self.coder.Decode(req.Params, &args); err != nil { return nil, shared.NewDecodeParamError(err.Error()) } sender := common.HexToAddress(args.Sender) registry := registrar.New(self.xeth) _, err := registry.SetUrlToHash(sender, common.HexToHash(args.ContentHash), args.Url) if err != nil { return false, err } return true, nil }
func (self *adminApi) SetHashReg(req *shared.Request) (interface{}, error) { args := new(SetHashRegArgs) if err := self.coder.Decode(req.Params, &args); err != nil { return nil, shared.NewDecodeParamError(err.Error()) } reg := registrar.New(self.xeth) sender := common.HexToAddress(args.Sender) txhash, err := reg.SetHashReg(args.HashReg, sender) if err != nil { return false, err } return txhash, nil }
func (self *adminApi) SetUrlHint(req *shared.Request) (interface{}, error) { args := new(SetUrlHintArgs) if err := self.coder.Decode(req.Params, &args); err != nil { return nil, shared.NewDecodeParamError(err.Error()) } urlHint := args.UrlHint sender := common.HexToAddress(args.Sender) reg := registrar.New(self.xeth) txhash, err := reg.SetUrlHint(urlHint, sender) if err != nil { return nil, err } return txhash, nil }
func (self *adminApi) Register(req *shared.Request) (interface{}, error) { args := new(RegisterArgs) if err := self.coder.Decode(req.Params, &args); err != nil { return nil, shared.NewDecodeParamError(err.Error()) } sender := common.HexToAddress(args.Sender) // sender and contract address are passed as hex strings codeb := self.xeth.CodeAtBytes(args.Address) codeHash := common.BytesToHash(crypto.Sha3(codeb)) contentHash := common.HexToHash(args.ContentHashHex) registry := registrar.New(self.xeth) _, err := registry.SetHashToHash(sender, codeHash, contentHash) if err != nil { return false, err } return true, nil }
// also called by admin.contractInfo.get func FetchDocsForContract(contractAddress string, xeth *xeth.XEth, ds *docserver.DocServer) (content []byte, err error) { // retrieve contract hash from state codehex := xeth.CodeAt(contractAddress) codeb := xeth.CodeAtBytes(contractAddress) if codehex == "0x" { err = fmt.Errorf("contract (%v) not found", contractAddress) return } codehash := common.BytesToHash(crypto.Sha3(codeb)) // set up nameresolver with natspecreg + urlhint contract addresses reg := registrar.New(xeth) // resolve host via HashReg/UrlHint Resolver hash, err := reg.HashToHash(codehash) if err != nil { return } if ds.HasScheme("bzz") { content, err = ds.Get("bzz://"+hash.Hex()[2:], "") if err == nil { // non-fatal return } err = nil //falling back to urlhint } uri, err := reg.HashToUrl(hash) if err != nil { return } // get content via http client and authenticate content using hash content, err = ds.GetAuthContent(uri, hash) if err != nil { return } return }
// 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 }
// 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) }
// 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) }
// end to end test func TestNatspecE2E(t *testing.T) { t.Skip() tf := testInit(t) defer tf.ethereum.Stop() addr, _ := tf.ethereum.Etherbase() // create a contractInfo file (mock cloud-deployed contract metadocs) // incidentally this is the info for the HashReg contract itself ioutil.WriteFile("/tmp/"+testFileName, []byte(testContractInfo), os.ModePerm) dochash := crypto.Keccak256Hash([]byte(testContractInfo)) // take the codehash for the contract we wanna test codeb := tf.xeth.CodeAtBytes(registrar.HashRegAddr) codehash := crypto.Keccak256Hash(codeb) reg := registrar.New(tf.xeth) _, err := reg.SetHashToHash(addr, codehash, dochash) if err != nil { t.Errorf("error registering: %v", err) } _, err = reg.SetUrlToHash(addr, dochash, "file:///"+testFileName) if err != nil { t.Errorf("error registering: %v", err) } if !processTxs(tf, t, 5) { return } // NatSpec info for register method of HashReg contract installed // now using the same transactions to check confirm messages tf.wantNatSpec = true // this is set so now the backend uses natspec confirmation _, err = reg.SetHashToHash(addr, codehash, dochash) if err != nil { t.Errorf("error calling contract registry: %v", err) } fmt.Printf("GlobalRegistrar: %v, HashReg: %v, UrlHint: %v\n", registrar.GlobalRegistrarAddr, registrar.HashRegAddr, registrar.UrlHintAddr) if tf.lastConfirm != testExpNotice { t.Errorf("Wrong confirm message. expected\n'%v', got\n'%v'", testExpNotice, tf.lastConfirm) } // test unknown method exp := fmt.Sprintf(testExpNotice2, registrar.HashRegAddr) _, err = reg.SetOwner(addr) if err != nil { t.Errorf("error setting owner: %v", err) } if tf.lastConfirm != exp { t.Errorf("Wrong confirm message, expected\n'%v', got\n'%v'", exp, tf.lastConfirm) } // test unknown contract exp = fmt.Sprintf(testExpNotice3, registrar.UrlHintAddr) _, err = reg.SetUrlToHash(addr, dochash, "file:///test.content") if err != nil { t.Errorf("error registering: %v", err) } if tf.lastConfirm != exp { t.Errorf("Wrong confirm message, expected '%v', got '%v'", exp, tf.lastConfirm) } }
func testInit(t *testing.T) (self *testFrontend) { // initialise and start minimal ethereum stack ethereum, err := testEth(t) if err != nil { t.Errorf("error creating ethereum: %v", err) return } err = ethereum.Start(nil) if err != nil { t.Errorf("error starting ethereum: %v", err) return } // mock frontend self = &testFrontend{t: t, ethereum: ethereum} self.xeth = xe.New(nil, self) self.wait = self.xeth.UpdateState() addr, _ := self.ethereum.Etherbase() // initialise the registry contracts reg := registrar.New(self.xeth) registrar.GlobalRegistrarAddr = "0x0" 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) } 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, 1) { t.Errorf("error mining txs") } recU := self.xeth.GetTxReceipt(common.HexToHash(txU)) if recU == nil { t.Fatalf("blockchain error creating UrlHint") } registrar.UrlHintAddr = recU.ContractAddress.Hex() return }
func TestContract(t *testing.T) { t.Skip("contract testing is implemented with mining in ethash test mode. This takes about 7seconds to run. Unskip and run on demand") coinbase := common.HexToAddress(testAddress) tmp, repl, ethereum := testREPL(t, func(conf *eth.Config) { conf.Etherbase = coinbase conf.PowTest = true }) if err := ethereum.Start(); err != nil { t.Errorf("error starting ethereum: %v", err) return } defer ethereum.Stop() defer os.RemoveAll(tmp) reg := registrar.New(repl.xeth) _, err := reg.SetGlobalRegistrar("", coinbase) if err != nil { t.Errorf("error setting HashReg: %v", err) } _, err = reg.SetHashReg("", coinbase) if err != nil { t.Errorf("error setting HashReg: %v", err) } _, err = reg.SetUrlHint("", coinbase) if err != nil { t.Errorf("error setting HashReg: %v", err) } /* 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 */ source := `contract test {\n` + " /// @notice Will multiply `a` by 7." + `\n` + ` function multiply(uint a) returns(uint d) {\n` + ` return a * 7;\n` + ` }\n` + `}\n` if checkEvalJSON(t, repl, `admin.stopNatSpec()`, `true`) != nil { return } contractInfo, err := ioutil.ReadFile("info_test.json") if err != nil { t.Fatalf("%v", err) } if checkEvalJSON(t, repl, `primary = eth.accounts[0]`, `"`+testAddress+`"`) != nil { return } if checkEvalJSON(t, repl, `source = "`+source+`"`, `"`+source+`"`) != nil { return } // if solc is found with right version, test it, otherwise read from file sol, err := compiler.New("") if err != nil { t.Logf("solc not found: mocking contract compilation step") } else if sol.Version() != solcVersion { t.Logf("WARNING: solc different version found (%v, test written for %v, may need to update)", sol.Version(), solcVersion) } if err != nil { info, err := ioutil.ReadFile("info_test.json") if err != nil { t.Fatalf("%v", err) } _, err = repl.re.Run(`contract = JSON.parse(` + strconv.Quote(string(info)) + `)`) if err != nil { t.Errorf("%v", err) } } else { if checkEvalJSON(t, repl, `contract = eth.compile.solidity(source).test`, string(contractInfo)) != nil { return } } if checkEvalJSON(t, repl, `contract.code`, `"0x605880600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b603d6004803590602001506047565b8060005260206000f35b60006007820290506053565b91905056"`) != nil { return } if checkEvalJSON( t, repl, `contractaddress = eth.sendTransaction({from: primary, data: contract.code})`, `"0x46d69d55c3c4b86a924a92c9fc4720bb7bce1d74"`, ) != nil { return } if !processTxs(repl, t, 8) { return } callSetup := `abiDef = JSON.parse('[{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"type":"function"}]'); Multiply7 = eth.contract(abiDef); multiply7 = Multiply7.at(contractaddress); ` _, err = repl.re.Run(callSetup) if err != nil { t.Errorf("unexpected error setting up contract, got %v", err) return } expNotice := "" if repl.lastConfirm != expNotice { t.Errorf("incorrect confirmation message: expected %v, got %v", expNotice, repl.lastConfirm) return } if checkEvalJSON(t, repl, `admin.startNatSpec()`, `true`) != nil { return } if checkEvalJSON(t, repl, `multiply7.multiply.sendTransaction(6, { from: primary })`, `"0x4ef9088431a8033e4580d00e4eb2487275e031ff4163c7529df0ef45af17857b"`) != nil { return } if !processTxs(repl, t, 1) { return } expNotice = `About to submit transaction (no NatSpec info found for contract: content hash not found for '0x87e2802265838c7f14bb69eecd2112911af6767907a702eeaa445239fb20711b'): {"params":[{"to":"0x46d69d55c3c4b86a924a92c9fc4720bb7bce1d74","data": "0xc6888fa10000000000000000000000000000000000000000000000000000000000000006"}]}` if repl.lastConfirm != expNotice { t.Errorf("incorrect confirmation message: expected\n%v, got\n%v", expNotice, repl.lastConfirm) return } var contentHash = `"0x86d2b7cf1e72e9a7a3f8d96601f0151742a2f780f1526414304fbe413dc7f9bd"` if sol != nil && solcVersion != sol.Version() { modContractInfo := versionRE.ReplaceAll(contractInfo, []byte(`"compilerVersion":"`+sol.Version()+`"`)) fmt.Printf("modified contractinfo:\n%s\n", modContractInfo) contentHash = `"` + common.ToHex(crypto.Sha3([]byte(modContractInfo))) + `"` } if checkEvalJSON(t, repl, `filename = "/tmp/info.json"`, `"/tmp/info.json"`) != nil { return } if checkEvalJSON(t, repl, `contentHash = admin.saveInfo(contract.info, filename)`, contentHash) != nil { return } if checkEvalJSON(t, repl, `admin.register(primary, contractaddress, contentHash)`, `true`) != nil { return } if checkEvalJSON(t, repl, `admin.registerUrl(primary, contentHash, "file://"+filename)`, `true`) != nil { return } if checkEvalJSON(t, repl, `admin.startNatSpec()`, `true`) != nil { return } if !processTxs(repl, t, 3) { return } if checkEvalJSON(t, repl, `multiply7.multiply.sendTransaction(6, { from: primary })`, `"0x66d7635c12ad0b231e66da2f987ca3dfdca58ffe49c6442aa55960858103fd0c"`) != nil { return } if !processTxs(repl, t, 1) { return } expNotice = "Will multiply 6 by 7." if repl.lastConfirm != expNotice { t.Errorf("incorrect confirmation message: expected\n%v, got\n%v", expNotice, repl.lastConfirm) return } }
func New(xe *xeth.XEth) (self *EthReg) { self = &EthReg{backend: xe} self.registry = registrar.New(xe) return }