diff options
author | Jeffrey Wilcke <jeffrey@ethereum.org> | 2015-05-08 18:43:31 +0800 |
---|---|---|
committer | Jeffrey Wilcke <jeffrey@ethereum.org> | 2015-05-08 18:43:31 +0800 |
commit | 45c070fc8b0b8c98db97a9d25a0ca2fcaef26289 (patch) | |
tree | c37120a02ed0bf7d436adad0f7efb5c1384469f0 /common/natspec/natspec_e2e_test.go | |
parent | 637b2415d969a97b3d119be2aceb9411458d00d9 (diff) | |
parent | 009b2216921b15962f2612687c1460a8342d49d6 (diff) | |
download | go-tangerine-45c070fc8b0b8c98db97a9d25a0ca2fcaef26289.tar.gz go-tangerine-45c070fc8b0b8c98db97a9d25a0ca2fcaef26289.tar.zst go-tangerine-45c070fc8b0b8c98db97a9d25a0ca2fcaef26289.zip |
Merge pull request #833 from ethersphere/frontier/solidity
solidity compiler and contract metadocs integration
Diffstat (limited to 'common/natspec/natspec_e2e_test.go')
-rw-r--r-- | common/natspec/natspec_e2e_test.go | 328 |
1 files changed, 115 insertions, 213 deletions
diff --git a/common/natspec/natspec_e2e_test.go b/common/natspec/natspec_e2e_test.go index e54b9ee96..f9b0c1dcc 100644 --- a/common/natspec/natspec_e2e_test.go +++ b/common/natspec/natspec_e2e_test.go @@ -1,8 +1,8 @@ package natspec import ( + "fmt" "io/ioutil" - "math/big" "os" "testing" @@ -14,39 +14,26 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/rpc" xe "github.com/ethereum/go-ethereum/xeth" ) -type testFrontend struct { - t *testing.T - ethereum *eth.Ethereum - xeth *xe.XEth - api *rpc.EthereumApi - coinbase string - stateDb *state.StateDB - txc uint64 - lastConfirm string - makeNatSpec bool -} - const ( - testAccount = "e273f01c99144c438695e10f24926dc1f9fbf62d" - testBalance = "1000000000000" -) + testBalance = "10000000000000000000" -const testFileName = "long_file_name_for_testing_registration_of_URLs_longer_than_32_bytes.content" + testFileName = "long_file_name_for_testing_registration_of_URLs_longer_than_32_bytes.content" -const testNotice = "Register key `utils.toHex(_key)` <- content `utils.toHex(_content)`" -const testExpNotice = "Register key 0xadd1a7d961cff0242089674ec2ef6fca671ab15e1fe80e38859fc815b98d88ab <- content 0xc00d5bcc872e17813df6ec5c646bb281a6e2d3b454c2c400c78192adf3344af9" -const testExpNotice2 = `About to submit transaction (NatSpec notice error "abi key does not match any method"): {"id":6,"jsonrpc":"2.0","method":"eth_transact","params":[{"from":"0xe273f01c99144c438695e10f24926dc1f9fbf62d","to":"0xb737b91f8e95cf756766fc7c62c9a8ff58470381","value":"100000000000","gas":"100000","gasPrice":"100000","data":"0x31e12c20"}]}` -const testExpNotice3 = `About to submit transaction (no NatSpec info found for contract): {"id":6,"jsonrpc":"2.0","method":"eth_transact","params":[{"from":"0xe273f01c99144c438695e10f24926dc1f9fbf62d","to":"0x8b839ad85686967a4f418eccc81962eaee314ac3","value":"100000000000","gas":"100000","gasPrice":"100000","data":"0x300a3bbfc00d5bcc872e17813df6ec5c646bb281a6e2d3b454c2c400c78192adf3344af900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000"}]}` + testNotice = "Register key `utils.toHex(_key)` <- content `utils.toHex(_content)`" -const testUserDoc = ` + testExpNotice = "Register key 0xadd1a7d961cff0242089674ec2ef6fca671ab15e1fe80e38859fc815b98d88ab <- content 0xb3a2dea218de5d8bbe6c4645aadbf67b5ab00ecb1a9ec95dbdad6a0eed3e41a7" + + 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"}]}` +) + +const ( + testUserDoc = ` { - "source": "...", - "language": "Solidity", - "languageVersion": 1, "methods": { "register(uint256,uint256)": { "notice": "` + testNotice + `" @@ -60,8 +47,7 @@ const testUserDoc = ` ] } ` - -const testABI = ` + testAbiDefinition = ` [{ "name": "register", "constant": false, @@ -77,70 +63,81 @@ const testABI = ` }] ` -const testDocs = ` + testContractInfo = ` { - "userdoc": ` + testUserDoc + `, - "abi": ` + testABI + ` + "userDoc": ` + testUserDoc + `, + "abiDefinition": ` + testAbiDefinition + ` } ` +) + +type testFrontend struct { + t *testing.T + // resolver *resolver.Resolver + ethereum *eth.Ethereum + xeth *xe.XEth + coinbase common.Address + stateDb *state.StateDB + txc uint64 + lastConfirm string + wantNatSpec bool +} -func (f *testFrontend) UnlockAccount(acc []byte) bool { - f.t.Logf("Unlocking account %v\n", common.Bytes2Hex(acc)) - f.ethereum.AccountManager().Unlock(acc, "password") +func (self *testFrontend) UnlockAccount(acc []byte) bool { + self.ethereum.AccountManager().Unlock(acc, "password") return true } -func (f *testFrontend) ConfirmTransaction(tx string) bool { - //f.t.Logf("ConfirmTransaction called tx = %v", tx) - if f.makeNatSpec { +func (self *testFrontend) ConfirmTransaction(tx string) bool { + if self.wantNatSpec { ds, err := docserver.New("/tmp/") if err != nil { - f.t.Errorf("Error creating DocServer: %v", err) + self.t.Errorf("Error creating DocServer: %v", err) } - f.lastConfirm = GetNotice(f.xeth, tx, ds) + self.lastConfirm = GetNotice(self.xeth, tx, ds) } return true } -var port = 30300 - func testEth(t *testing.T) (ethereum *eth.Ethereum, err error) { + os.RemoveAll("/tmp/eth-natspec/") - err = os.MkdirAll("/tmp/eth-natspec/keys/e273f01c99144c438695e10f24926dc1f9fbf62d/", os.ModePerm) + + err = os.MkdirAll("/tmp/eth-natspec/keys", os.ModePerm) if err != nil { - t.Errorf("%v", err) - return + panic(err) } - err = os.MkdirAll("/tmp/eth-natspec/data", os.ModePerm) + + // create a testAddress + ks := crypto.NewKeyStorePassphrase("/tmp/eth-natspec/keys") + am := accounts.NewManager(ks) + testAccount, err := am.NewAccount("password") if err != nil { - t.Errorf("%v", err) - return + panic(err) } - ks := crypto.NewKeyStorePlain("/tmp/eth-natspec/keys") - ioutil.WriteFile("/tmp/eth-natspec/keys/e273f01c99144c438695e10f24926dc1f9fbf62d/e273f01c99144c438695e10f24926dc1f9fbf62d", - []byte(`{"Id":"RhRXD+fNRKS4jx+7ZfEsNA==","Address":"4nPwHJkUTEOGleEPJJJtwfn79i0=","PrivateKey":"h4ACVpe74uIvi5Cg/2tX/Yrm2xdr3J7QoMbMtNX2CNc="}`), os.ModePerm) + testAddress := common.Bytes2Hex(testAccount.Address) + + // set up mock genesis with balance on the testAddress + core.GenesisData = []byte(`{ + "` + testAddress + `": {"balance": "` + testBalance + `"} + }`) - port++ + // only use minimalistic stack with no networking ethereum, err = eth.New(ð.Config{ DataDir: "/tmp/eth-natspec", - AccountManager: accounts.NewManager(ks), - Name: "test", + AccountManager: am, + MaxPeers: 0, }) if err != nil { - t.Errorf("%v", err) - return + panic(err) } return } func testInit(t *testing.T) (self *testFrontend) { - - core.GenesisData = []byte(`{ - "` + testAccount + `": {"balance": "` + testBalance + `"} - }`) - + // initialise and start minimal ethereum stack ethereum, err := testEth(t) if err != nil { t.Errorf("error creating ethereum: %v", err) @@ -152,190 +149,95 @@ func testInit(t *testing.T) (self *testFrontend) { return } + // mock frontend self = &testFrontend{t: t, ethereum: ethereum} self.xeth = xe.New(ethereum, self) - self.api = rpc.NewEthereumApi(self.xeth) - addr := self.xeth.Coinbase() + addr, _ := ethereum.Etherbase() self.coinbase = addr - if addr != "0x"+testAccount { - t.Errorf("CoinBase %v does not match TestAccount 0x%v", addr, testAccount) - } - t.Logf("CoinBase is %v", addr) - - balance := self.xeth.BalanceAt(testAccount) - /*if balance != core.TestBalance { - t.Errorf("Balance %v does not match TestBalance %v", balance, core.TestBalance) - }*/ - t.Logf("Balance is %v", balance) - self.stateDb = self.ethereum.ChainManager().State().Copy() - return - -} - -func (self *testFrontend) insertTx(addr, contract, fnsig string, args []string) { - - //cb := common.HexToAddress(self.coinbase) - //coinbase := self.ethereum.ChainManager().State().GetStateObject(cb) + // initialise the registry contracts + // self.resolver.CreateContracts(addr) + resolver.New(self.xeth).CreateContracts(addr) + self.applyTxs() + // t.Logf("HashReg contract registered at %v", resolver.HashRegContractAddress) + // t.Logf("URLHint contract registered at %v", resolver.UrlHintContractAddress) - hash := common.Bytes2Hex(crypto.Sha3([]byte(fnsig))) - data := "0x" + hash[0:8] - for _, arg := range args { - data = data + common.Bytes2Hex(common.Hex2BytesFixed(arg, 32)) - } - self.t.Logf("Tx data: %v", data) - - jsontx := ` -[{ - "from": "` + addr + `", - "to": "` + contract + `", - "value": "100000000000", - "gas": "100000", - "gasPrice": "100000", - "data": "` + data + `" -}] -` - req := &rpc.RpcRequest{ - Jsonrpc: "2.0", - Method: "eth_transact", - Params: []byte(jsontx), - Id: 6, - } - - var reply interface{} - err0 := self.api.GetRequestReply(req, &reply) - if err0 != nil { - self.t.Errorf("GetRequestReply error: %v", err0) - } - - //self.xeth.Transact(addr, contract, "100000000000", "100000", "100000", data) + return } +// this is needed for transaction to be applied to the state in testing +// the heavy lifing is done in XEth.ApplyTestTxs +// this is fragile, +// and does process leaking since xeth loops cannot quit safely +// should be replaced by proper mining with testDAG for easy full integration tests func (self *testFrontend) applyTxs() { - - cb := common.HexToAddress(self.coinbase) - block := self.ethereum.ChainManager().NewBlock(cb) - coinbase := self.stateDb.GetStateObject(cb) - coinbase.SetGasPool(big.NewInt(10000000)) - txs := self.ethereum.TxPool().GetQueuedTransactions() - - for i := 0; i < len(txs); i++ { - for _, tx := range txs { - //self.t.Logf("%v %v %v", i, tx.Nonce(), self.txc) - if tx.Nonce() == self.txc { - _, gas, err := core.ApplyMessage(core.NewEnv(self.stateDb, self.ethereum.ChainManager(), tx, block), tx, coinbase) - //self.ethereum.TxPool().RemoveSet([]*types.Transaction{tx}) - self.t.Logf("ApplyMessage: gas %v err %v", gas, err) - self.txc++ - } - } - } - - //self.ethereum.TxPool().RemoveSet(txs) - self.xeth = self.xeth.WithState(self.stateDb) - -} - -func (self *testFrontend) registerURL(hash common.Hash, url string) { - hashHex := common.Bytes2Hex(hash[:]) - urlBytes := []byte(url) - var bb bool = true - var cnt byte - for bb { - bb = len(urlBytes) > 0 - urlb := urlBytes - if len(urlb) > 32 { - urlb = urlb[:32] - } - urlHex := common.Bytes2Hex(urlb) - self.insertTx(self.coinbase, resolver.URLHintContractAddress, "register(uint256,uint8,uint256)", []string{hashHex, common.Bytes2Hex([]byte{cnt}), urlHex}) - if len(urlBytes) > 32 { - urlBytes = urlBytes[32:] - } else { - urlBytes = nil - } - cnt++ - } -} - -func (self *testFrontend) setOwner() { - - self.insertTx(self.coinbase, resolver.HashRegContractAddress, "setowner()", []string{}) - - /*owner := self.xeth.StorageAt("0x"+resolver.HashRegContractAddress, "0x0000000000000000000000000000000000000000000000000000000000000000") - self.t.Logf("owner = %v", owner) - if owner != self.coinbase { - self.t.Errorf("setowner() unsuccessful, owner != coinbase") - }*/ -} - -func (self *testFrontend) registerNatSpec(codehash, dochash common.Hash) { - - codeHex := common.Bytes2Hex(codehash[:]) - docHex := common.Bytes2Hex(dochash[:]) - self.insertTx(self.coinbase, resolver.HashRegContractAddress, "register(uint256,uint256)", []string{codeHex, docHex}) -} - -func (self *testFrontend) testResolver() *resolver.Resolver { - return resolver.New(self.xeth, resolver.URLHintContractAddress, resolver.HashRegContractAddress) + self.txc, self.xeth = self.xeth.ApplyTestTxs(self.stateDb, self.coinbase, self.txc) + return } +// end to end test func TestNatspecE2E(t *testing.T) { - t.Skip() + // t.Skip() tf := testInit(t) defer tf.ethereum.Stop() - resolver.CreateContracts(tf.xeth, testAccount) - t.Logf("URLHint contract registered at %v", resolver.URLHintContractAddress) - t.Logf("HashReg contract registered at %v", resolver.HashRegContractAddress) - tf.applyTxs() - - ioutil.WriteFile("/tmp/"+testFileName, []byte(testDocs), os.ModePerm) - dochash := common.BytesToHash(crypto.Sha3([]byte(testDocs))) + // create a contractInfo file (mock cloud-deployed contract metadocs) + // incidentally this is the info for the registry contract itself + ioutil.WriteFile("/tmp/"+testFileName, []byte(testContractInfo), os.ModePerm) + dochash := common.BytesToHash(crypto.Sha3([]byte(testContractInfo))) - codehex := tf.xeth.CodeAt(resolver.HashRegContractAddress) - codehash := common.BytesToHash(crypto.Sha3(common.Hex2Bytes(codehex[2:]))) + // take the codehash for the contract we wanna test + // codehex := tf.xeth.CodeAt(resolver.HashRegContractAddress) + codeb := tf.xeth.CodeAtBytes(resolver.HashRegContractAddress) + codehash := common.BytesToHash(crypto.Sha3(codeb)) - tf.setOwner() - tf.registerNatSpec(codehash, dochash) - tf.registerURL(dochash, "file:///"+testFileName) - tf.applyTxs() - - chash, err := tf.testResolver().KeyToContentHash(codehash) + // use resolver to register codehash->dochash->url + registry := resolver.New(tf.xeth) + _, err := registry.Register(tf.coinbase, codehash, dochash, "file:///"+testFileName) if err != nil { - t.Errorf("Can't find content hash") - } - t.Logf("chash = %x err = %v", chash, err) - url, err2 := tf.testResolver().ContentHashToUrl(dochash) - if err2 != nil { - t.Errorf("Can't find URL hint") + t.Errorf("error registering: %v", err) } - t.Logf("url = %v err = %v", url, err2) + // apply txs to the state + tf.applyTxs() // NatSpec info for register method of HashReg contract installed // now using the same transactions to check confirm messages - tf.makeNatSpec = true - tf.registerNatSpec(codehash, dochash) - t.Logf("Confirm message: %v\n", tf.lastConfirm) + tf.wantNatSpec = true // this is set so now the backend uses natspec confirmation + _, err = registry.RegisterContentHash(tf.coinbase, codehash, dochash) + if err != nil { + t.Errorf("error calling contract registry: %v", err) + } + if tf.lastConfirm != testExpNotice { - t.Errorf("Wrong confirm message, expected '%v', got '%v'", testExpNotice, tf.lastConfirm) + t.Errorf("Wrong confirm message. expected '%v', got '%v'", testExpNotice, tf.lastConfirm) } - tf.setOwner() - t.Logf("Confirm message for unknown method: %v\n", tf.lastConfirm) - if tf.lastConfirm != testExpNotice2 { - t.Errorf("Wrong confirm message, expected '%v', got '%v'", testExpNotice2, tf.lastConfirm) + // test unknown method + exp := fmt.Sprintf(testExpNotice2, resolver.HashRegContractAddress) + _, err = registry.SetOwner(tf.coinbase) + if err != nil { + t.Errorf("error setting owner: %v", err) + } + + if tf.lastConfirm != exp { + t.Errorf("Wrong confirm message, expected '%v', got '%v'", exp, tf.lastConfirm) + } + + // test unknown contract + exp = fmt.Sprintf(testExpNotice3, resolver.UrlHintContractAddress) + + _, err = registry.RegisterUrl(tf.coinbase, dochash, "file:///test.content") + if err != nil { + t.Errorf("error registering: %v", err) } - tf.registerURL(dochash, "file:///test.content") - t.Logf("Confirm message for unknown contract: %v\n", tf.lastConfirm) - if tf.lastConfirm != testExpNotice3 { - t.Errorf("Wrong confirm message, expected '%v', got '%v'", testExpNotice3, tf.lastConfirm) + if tf.lastConfirm != exp { + t.Errorf("Wrong confirm message, expected '%v', got '%v'", exp, tf.lastConfirm) } } |