diff --git a/erisdb/erisdbss/http.go b/erisdb/erisdbss/http.go index 22d60ecfddc286d574d78531ae4129449704f948..13a07c40f99c700fbb2e1041cbe5557e2dc9e106 100644 --- a/erisdb/erisdbss/http.go +++ b/erisdb/erisdbss/http.go @@ -4,7 +4,6 @@ package erisdbss import ( "bytes" "encoding/json" - "fmt" "github.com/eris-ltd/erisdb/server" "github.com/gin-gonic/gin" "github.com/tendermint/tendermint/binary" @@ -21,7 +20,7 @@ moniker = "anothertester" seeds = "" fast_sync = false db_backend = "leveldb" -log_level = "debug" +log_level = "warn" node_laddr = "" ` @@ -83,7 +82,7 @@ func (this *ServerServer) ShutDown() { // Handle incoming requests. func (this *ServerServer) handleFunc(c *gin.Context) { - fmt.Println("INCOMING MESSAGE") + log.Debug("Incoming message") r := c.Request var buf bytes.Buffer n, errR := buf.ReadFrom(r.Body) @@ -99,13 +98,13 @@ func (this *ServerServer) handleFunc(c *gin.Context) { http.Error(c.Writer, "Failed to decode json.", 400) return } - fmt.Println("STARTING TO ADD") + log.Debug("Starting to add.") resp, errA := this.serverManager.add(reqData) if errA != nil { http.Error(c.Writer, "Internal error: "+errA.Error(), 500) return } - fmt.Printf("WORK DONE: %v\n", resp) + log.Debug("Work done.", "URL", resp.URL) w := c.Writer enc := json.NewEncoder(w) enc.Encode(resp) diff --git a/erisdb/erisdbss/log.go b/erisdb/erisdbss/log.go new file mode 100644 index 0000000000000000000000000000000000000000..719216427a0cbd239e0ae187dcfac8bf14604a72 --- /dev/null +++ b/erisdb/erisdbss/log.go @@ -0,0 +1,7 @@ +package erisdbss + +import ( + "github.com/tendermint/log15" +) + +var log = log15.New("module", "eris/serverserver") diff --git a/erisdb/erisdbss/server_manager.go b/erisdb/erisdbss/server_manager.go index 0cee9966c18caee199df3770147ad06e7a13a4ab..a03aa312940c6bd8bf5c1ff13ad11d67300a648c 100644 --- a/erisdb/erisdbss/server_manager.go +++ b/erisdb/erisdbss/server_manager.go @@ -6,6 +6,7 @@ import ( "github.com/eris-ltd/erisdb/server" "github.com/tendermint/tendermint/binary" . "github.com/tendermint/tendermint/common" + "github.com/eris-ltd/erisdb/files" "os" "os/exec" "path" @@ -42,7 +43,7 @@ func newCmdProcess(cmd *exec.Cmd, token string) *CmdProcess { } func (this *CmdProcess) Start(doneChan chan<- error) { - fmt.Println("Starting erisdb process") + log.Debug("Starting erisdb process") reader, errSP := this.cmd.StdoutPipe() if errSP != nil { @@ -59,9 +60,9 @@ func (this *CmdProcess) Start(doneChan chan<- error) { fmt.Println("process started, waiting for token") for scanner.Scan() { text := scanner.Text() - fmt.Println(text) + log.Debug(text) if strings.Index(text, this.token) != -1 { - fmt.Println("Token found: " + text) + log.Debug("Token found", "token", this.token) break } } @@ -70,7 +71,7 @@ func (this *CmdProcess) Start(doneChan chan<- error) { doneChan <- fmt.Errorf("Error reading from process stdout:", err) return } - fmt.Println("erisdb ready") + log.Debug("ErisDB server ready.") doneChan <- nil } @@ -134,7 +135,7 @@ func reap(sm *ServerManager) { for len(sm.running) > 0 { task := sm.running[0] if task.maxDuration != 0 && time.Since(task.start) > task.maxDuration { - fmt.Printf("[SERVER REAPER] Closing down server on port: %d\n", task.port) + log.Debug("[SERVER REAPER] Closing down server.", "port", task.port) task.sp.Kill() sm.running = sm.running[1:] sm.idPool.ReleaseId(uint(task.port - PORT_BASE)) @@ -184,7 +185,7 @@ func (this *ServerManager) add(data *RequestData) (*ResponseData, error) { st := newServeTask(port, workDir, maxDur, proc) this.running = append(this.running, st) - URL := "http://" + config.Bind.Address + ":" + fmt.Sprintf("%d", port) + URL := fmt.Sprintf("http://%s:%d", config.Bind.Address, port) // TODO add validation data. The node should ideally return some post-deploy state data // and send it back with the server URL, so that the validity of the chain can be @@ -212,31 +213,37 @@ func (this *ServerManager) createWorkDir(data *RequestData, config *server.Serve genesisName := path.Join(workDir, "genesis.json") // Write config. - WriteFile(cfgName, []byte(TendermintConfigDefault)) + errCFG := files.WriteFileRW(cfgName, []byte(TendermintConfigDefault)) + if errCFG != nil { + return "", errCFG + } + log.Info("File written to %s.\n", cfgName) // Write validator. - errPV := writeJSON(data.PrivValidator, pvName) + errPV := writeJSON(pvName, data.PrivValidator) if errPV != nil { return "", errPV } + log.Info("File written to %s.\n", pvName) // Write genesis - errG := writeJSON(data.Genesis, genesisName) + errG := writeJSON(genesisName, data.Genesis) if errG != nil { return "", errG } + log.Info("File written to %s.\n", genesisName) // Write server config. errWC := server.WriteServerConfig(scName, config) if errWC != nil { return "", errWC } - + log.Info("File written to %s.\n", scName) return workDir, nil } // Used to write json files using tendermints binary package. -func writeJSON(v interface{}, file string) error { +func writeJSON(file string, v interface{}) error { var n int64 var errW error fo, errC := os.Create(file) @@ -251,7 +258,6 @@ func writeJSON(v interface{}, file string) error { if errL != nil { return errL } - fmt.Printf("File written to %s.\n", file) return nil } diff --git a/erisdb/params.go b/erisdb/params.go index ccab894429f6ddda91780b32b37842c558db4366..4f690db7e76209f88d77a36eb039474466e4dbe2 100644 --- a/erisdb/params.go +++ b/erisdb/params.go @@ -77,7 +77,7 @@ type ( } // Used when sending a transaction to be created and signed on the server - // (using the private key). + // (using the private key). This only uses the standard key type for now. TransactParam struct { PrivKey []byte `json:"priv_key"` Data []byte `json:"data"` diff --git a/erisdb/restServer.go b/erisdb/restServer.go index 4db79487f2efc4ac0b5276755ef085b02d7c810f..79714d7a9872ebbf8645f366e7270e999fc36a0d 100644 --- a/erisdb/restServer.go +++ b/erisdb/restServer.go @@ -30,7 +30,7 @@ func NewRestServer(codec rpc.Codec, pipe ep.Pipe, eventSubs *EventSubscriptions) // Starting the server means registering all the handlers with the router. func (this *RestServer) Start(config *server.ServerConfig, router *gin.Engine) { // Accounts - router.GET("/accounts", this.handleAccounts) + router.GET("/accounts", parseQuery, this.handleAccounts) router.GET("/accounts/:address", addressParam, this.handleAccount) router.GET("/accounts/:address/storage", addressParam, this.handleStorage) router.GET("/accounts/:address/storage/:key", addressParam, keyParam, this.handleStorageAt) @@ -40,7 +40,7 @@ func (this *RestServer) Start(config *server.ServerConfig, router *gin.Engine) { router.GET("/blockchain/genesis_hash", this.handleGenesisHash) router.GET("/blockchain/latest_block_height", this.handleLatestBlockHeight) router.GET("/blockchain/latest_block", this.handleLatestBlock) - router.GET("/blockchain/blocks", this.handleBlocks) + router.GET("/blockchain/blocks", parseQuery, this.handleBlocks) router.GET("/blockchain/block/:height", heightParam, this.handleBlock) // Consensus router.GET("/consensus", this.handleConsensusState) @@ -61,7 +61,7 @@ func (this *RestServer) Start(config *server.ServerConfig, router *gin.Engine) { router.GET("/txpool", this.handleUnconfirmedTxs) // Code execution router.POST("/calls/:address", this.handleCall) - router.POST("/calls/", this.handleCallCode) + router.POST("/calls", this.handleCallCode) // Unsafe router.GET("/unsafe/pa_generator", this.handleGenPrivAcc) router.POST("/unsafe/txpool", this.handleTransact) @@ -186,14 +186,18 @@ func (this *RestServer) handleLatestBlock(c *gin.Context) { } func (this *RestServer) handleBlocks(c *gin.Context) { - // TODO fix when query structure has been decided on. - // rfd := &RangeFilterData{0, 0} - //blocks, err := this.pipe.Blockchain().Blocks(rfd) - //if err != nil { - // c.AbortWithError(500, err) - //} - //c.Writer.WriteHeader(200) - //this.codec.Encode(blocks, c.Writer) + var filters []*ep.FilterData + fs, exists := c.Get("filters") + if exists { + filters = fs.([]*ep.FilterData) + } + + blocks, err := this.pipe.Blockchain().Blocks(filters) + if err != nil { + c.AbortWithError(500, err) + } + c.Writer.WriteHeader(200) + this.codec.Encode(blocks, c.Writer) } func (this *RestServer) handleBlock(c *gin.Context) { @@ -360,12 +364,12 @@ func (this *RestServer) handleCall(c *gin.Context) { } func (this *RestServer) handleCallCode(c *gin.Context) { - param := &CallParam{} + param := &CallCodeParam{} errD := this.codec.Decode(param, c.Request.Body) if errD != nil { c.AbortWithError(500, errD) } - call, err := this.pipe.Transactor().Call(param.Address, param.Data) + call, err := this.pipe.Transactor().CallCode(param.Code, param.Data) if err != nil { c.AbortWithError(500, err) } diff --git a/test/http_flood_test.go b/test/http_flood_test.go index bd45d00f633dfca69ba0c8cd1163bb9e1ae2377b..b2f61f2d373bbb56b8fc99ab31777b871742c277 100644 --- a/test/http_flood_test.go +++ b/test/http_flood_test.go @@ -24,8 +24,11 @@ func TestHttpFlooding(t *testing.T) { if err == nil { t.Logf("HTTP test: A total of %d http GET messages sent succesfully over %d seconds.\n", DURATION*PER_SEC, DURATION) } - errStop := serveProcess.Stop(time.Millisecond * 1000) + stopC := serveProcess.StopEventChannel() + errStop := serveProcess.Stop(0) + <- stopC assert.NoError(t, errStop, "Scumbag-ed!") + } func runHttp() error { diff --git a/test/temp/testdata.go b/test/temp/testdata.go deleted file mode 100644 index 6438a3984c3ff315526e8a1aa0efafe99cf97c8e..0000000000000000000000000000000000000000 --- a/test/temp/testdata.go +++ /dev/null @@ -1,73 +0,0 @@ -package test - -import ( - "github.com/tendermint/tendermint/state" - edb "github.com/eris-ltd/erisdb/erisdb" - ess "github.com/eris-ltd/erisdb/erisdb/erisdbss" -) - - -var privValidator = []byte(`{ - "address": "37236DF251AB70022B1DA351F08A20FB52443E37", - "pub_key": [1, "CB3688B7561D488A2A4834E1AEE9398BEF94844D8BDBBCA980C11E3654A45906"], - "priv_key": [1, "6B72D45EB65F619F11CE580C8CAED9E0BADC774E9C9C334687A65DCBAD2C4151CB3688B7561D488A2A4834E1AEE9398BEF94844D8BDBBCA980C11E3654A45906"], - "last_height": 0, - "last_round": 0, - "last_step": 0 -}`); - -var genesisDoc = []byte(`{ - "chain_id": "my_tests", - "accounts": [ - { - "address": "F81CB9ED0A868BD961C4F5BBC0E39B763B89FCB6", - "amount": 690000000000 - }, - { - "address": "0000000000000000000000000000000000000002", - "amount": 565000000000 - }, - { - "address": "9E54C9ECA9A3FD5D4496696818DA17A9E17F69DA", - "amount": 525000000000 - }, - { - "address": "0000000000000000000000000000000000000004", - "amount": 110000000000 - }, - { - "address": "37236DF251AB70022B1DA351F08A20FB52443E37", - "amount": 110000000000 - } - - ], - "validators": [ - { - "pub_key": [1, "CB3688B7561D488A2A4834E1AEE9398BEF94844D8BDBBCA980C11E3654A45906"], - "amount": 5000000000, - "unbond_to": [ - { - "address": "93E243AC8A01F723DE353A4FA1ED911529CCB6E5", - "amount": 5000000000 - } - ] - } - ] -}`); - -var serverDuration uint = 100 - -type TestData struct { - requestData *ess.RequestData -} - -func LoadTestData() *TestData { - codec := edb.NewTCodec() - pvd := &state.PrivValidator{} - _ = codec.DecodeBytes(pvd, privValidator) - genesis := &state.GenesisDoc{} - _ = codec.DecodeBytes(genesis, genesisDoc) - td := &TestData{} - td.requestData = &ess.RequestData{pvd, genesis, serverDuration} - return td -} \ No newline at end of file diff --git a/test/temp/web_api_test.go b/test/temp/web_api_test.go deleted file mode 100644 index 8656820afd6d49eef4bad330156461db414cced7..0000000000000000000000000000000000000000 --- a/test/temp/web_api_test.go +++ /dev/null @@ -1,143 +0,0 @@ -package test - -// Basic imports -import ( - "bytes" - "fmt" - // edb "github.com/eris-ltd/erisdb/erisdb" - ess "github.com/eris-ltd/erisdb/erisdb/erisdbss" - edb "github.com/eris-ltd/erisdb/erisdb" - ep "github.com/eris-ltd/erisdb/erisdb/pipe" - "github.com/eris-ltd/erisdb/rpc" - "github.com/eris-ltd/erisdb/server" - "github.com/gin-gonic/gin" - "github.com/stretchr/testify/suite" - // "io/ioutil" - "net/http" - "os" - "path" - "testing" - "time" -) - -const SS_URL = "http://localhost:1337/server" - -// -type WebApiSuite struct { - suite.Suite - baseDir string - serveProcess *server.ServeProcess - codec rpc.Codec - sUrl string - testData *TestData -} - -func (this *WebApiSuite) SetupSuite() { - gin.SetMode(gin.ReleaseMode) - baseDir := path.Join(os.TempDir(), "/.edbservers") - ss := ess.NewServerServer(baseDir) - proc := server.NewServeProcess(nil, ss) - _ = proc.Start() - this.serveProcess = proc - time.Sleep(1*time.Second) - this.testData = LoadTestData() - this.codec = edb.NewTCodec() - rBts, _ := this.codec.EncodeBytes(this.testData.requestData) - resp, _ := http.Post(SS_URL, "application/json", bytes.NewBuffer(rBts)) - rd := &ess.ResponseData{} - _ = this.codec.Decode(rd, resp.Body) - fmt.Println("Received URL: " + rd.URL) - this.sUrl = rd.URL - time.Sleep(1*time.Second) -} - -func (this *WebApiSuite) TearDownSuite() { - sec := this.serveProcess.StopEventChannel() - this.serveProcess.Stop(time.Millisecond) - <-sec - os.RemoveAll(this.baseDir) -} - -// ********************************************* Consensus ********************************************* - -func (this *WebApiSuite) Test_A0_ConsensusState() { - resp, errG := http.Get(this.sUrl + "/consensus") - this.NoError(errG) - ret := &ep.ConsensusState{} - errD := this.codec.Decode(ret, resp.Body) - this.NoError(errD) - fmt.Printf("Consensus state: %v\n", ret) -} - -func (this *WebApiSuite) Test_A1_Validators() { - resp, errG := http.Get(this.sUrl + "/consensus/validators") - this.NoError(errG) - ret := &ep.ValidatorList{} - errD := this.codec.Decode(ret, resp.Body) - this.NoError(errD) - fmt.Printf("Validators: %v\n", ret) -} - -// ********************************************* Network ********************************************* - -func (this *WebApiSuite) Test_B0_NetworkInfo() { - resp, errG := http.Get(this.sUrl + "/network") - this.NoError(errG) - ni := &ep.NetworkInfo{} - errD := this.codec.Decode(ni, resp.Body) - this.NoError(errD) - fmt.Printf("NetworkInfo: %v\n", ni) -} - -func (this *WebApiSuite) Test_B1_Moniker() { - resp, errG := http.Get(this.sUrl + "/network/moniker") - this.NoError(errG) - ret := &ep.Moniker{} - errD := this.codec.Decode(ret, resp.Body) - this.NoError(errD) - fmt.Printf("Moniker: %v\n", ret) -} - -func (this *WebApiSuite) Test_B2_Listening() { - resp, errG := http.Get(this.sUrl + "/network/listening") - this.NoError(errG) - ret := &ep.Listening{} - errD := this.codec.Decode(ret, resp.Body) - this.NoError(errD) - fmt.Printf("Listening: %v\n", ret) -} - -func (this *WebApiSuite) Test_B3_Listeners() { - resp, errG := http.Get(this.sUrl + "/network/listeners") - this.NoError(errG) - ret := &ep.Listeners{} - errD := this.codec.Decode(ret, resp.Body) - this.NoError(errD) - fmt.Printf("Listeners: %v\n", ret) -} - -func (this *WebApiSuite) Test_B4_Peers() { - resp, errG := http.Get(this.sUrl + "/network/peers") - this.NoError(errG) - ret := &ep.Peers{} - errD := this.codec.Decode(ret, resp.Body) - this.NoError(errD) - fmt.Printf("Listeners: %v\n", ret) -} - -// ********************************************* Transactions ********************************************* - -func (this *WebApiSuite) Test_C0_TransactContractCreate() { - resp, errG := http.Get(this.sUrl + "/unsafe/txpool") - this.NoError(errG) - ni := &ep.NetworkInfo{} - errD := this.codec.Decode(ni, resp.Body) - this.NoError(errD) - fmt.Printf("NetworkInfo: %v\n", ni) -} - -// ********************************************* Teardown ********************************************* - -func TestWebApiSuite(t *testing.T) { - suite.Run(t, &WebApiSuite{}) -} \ No newline at end of file diff --git a/test/testdata.go b/test/testdata.go new file mode 100644 index 0000000000000000000000000000000000000000..20c4d64a252bde317f9767f6999a1967936671c8 --- /dev/null +++ b/test/testdata.go @@ -0,0 +1,322 @@ +package test + +import ( + edb "github.com/eris-ltd/erisdb/erisdb" + ep "github.com/eris-ltd/erisdb/erisdb/pipe" + "github.com/tendermint/tendermint/account" + "github.com/tendermint/tendermint/state" + "github.com/tendermint/tendermint/types" +) + +var testDataJson = `{ + "chain_data": { + "priv_validator": { + "address": "37236DF251AB70022B1DA351F08A20FB52443E37", + "pub_key": [1, "CB3688B7561D488A2A4834E1AEE9398BEF94844D8BDBBCA980C11E3654A45906"], + "priv_key": [1, "6B72D45EB65F619F11CE580C8CAED9E0BADC774E9C9C334687A65DCBAD2C4151CB3688B7561D488A2A4834E1AEE9398BEF94844D8BDBBCA980C11E3654A45906"], + "last_height": 0, + "last_round": 0, + "last_step": 0 + }, + "genesis": { + "chain_id": "my_tests", + "accounts": [ + { + "address": "F81CB9ED0A868BD961C4F5BBC0E39B763B89FCB6", + "amount": 690000000000 + }, + { + "address": "0000000000000000000000000000000000000002", + "amount": 565000000000 + }, + { + "address": "9E54C9ECA9A3FD5D4496696818DA17A9E17F69DA", + "amount": 525000000000 + }, + { + "address": "0000000000000000000000000000000000000004", + "amount": 110000000000 + }, + { + "address": "37236DF251AB70022B1DA351F08A20FB52443E37", + "amount": 110000000000 + } + + ], + "validators": [ + { + "pub_key": [1, "CB3688B7561D488A2A4834E1AEE9398BEF94844D8BDBBCA980C11E3654A45906"], + "amount": 5000000000, + "unbond_to": [ + { + "address": "93E243AC8A01F723DE353A4FA1ED911529CCB6E5", + "amount": 5000000000 + } + ] + } + ] + } + }, + "input" : { + "account_address": "9FC1ECFCAE2A554D4D1A000D0D80F748E66359E3", + "storage_address": "", + "tx_create" : { + "address": "", + "priv_key": "6B72D45EB65F619F11CE580C8CAED9E0BADC774E9C9C334687A65DCBAD2C4151CB3688B7561D488A2A4834E1AEE9398BEF94844D8BDBBCA980C11E3654A45906", + "data": "5B33600060006101000A81548173FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF021916908302179055505B6102828061003B6000396000F3006000357C01000000000000000000000000000000000000000000000000000000009004806337F428411461004557806340C10F191461005A578063D0679D341461006E57005B610050600435610244565B8060005260206000F35B610068600435602435610082565B60006000F35B61007C600435602435610123565B60006000F35B600060009054906101000A900473FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1673FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF163373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1614156100DD576100E2565B61011F565B80600160005060008473FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1681526020019081526020016000206000828282505401925050819055505B5050565B80600160005060003373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF168152602001908152602001600020600050541061015E57610163565B610240565B80600160005060003373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16815260200190815260200160002060008282825054039250508190555080600160005060008473FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1681526020019081526020016000206000828282505401925050819055507F93EB3C629EB575EDAF0252E4F9FC0C5CCADA50496F8C1D32F0F93A65A8257EB560003373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1681526020018373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1681526020018281526020016000A15B5050565B6000600160005060008373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16815260200190815260200160002060005054905061027D565B91905056", + "fee" : 1000, + "gas_limit": 1000 + }, + "tx": { + "address": "9FC1ECFCAE2A554D4D1A000D0D80F748E66359E3", + "priv_key": "6B72D45EB65F619F11CE580C8CAED9E0BADC774E9C9C334687A65DCBAD2C4151CB3688B7561D488A2A4834E1AEE9398BEF94844D8BDBBCA980C11E3654A45906", + "data": "", + "fee" : 1000, + "gas_limit": 1000 + }, + "call_code": { + "code": "5B33600060006101000A81548173FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF021916908302179055505B6102828061003B6000396000F3006000357C01000000000000000000000000000000000000000000000000000000009004806337F428411461004557806340C10F191461005A578063D0679D341461006E57005B610050600435610244565B8060005260206000F35B610068600435602435610082565B60006000F35B61007C600435602435610123565B60006000F35B600060009054906101000A900473FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1673FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF163373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1614156100DD576100E2565B61011F565B80600160005060008473FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1681526020019081526020016000206000828282505401925050819055505B5050565B80600160005060003373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF168152602001908152602001600020600050541061015E57610163565B610240565B80600160005060003373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16815260200190815260200160002060008282825054039250508190555080600160005060008473FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1681526020019081526020016000206000828282505401925050819055507F93EB3C629EB575EDAF0252E4F9FC0C5CCADA50496F8C1D32F0F93A65A8257EB560003373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1681526020018373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1681526020018281526020016000A15B5050565B6000600160005060008373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16815260200190815260200160002060005054905061027D565B91905056", + "data": "" + }, + "block_range": { + "min": 0, + "max": 0 + } + }, + "output": { + "consensus_state": { + "height": 1, + "round": 0, + "step": 1, + "start_time": "", + "commit_time": "0001-01-01 00:00:00 +0000 UTC", + "validators": [{ + "address": "37236DF251AB70022B1DA351F08A20FB52443E37", + "pub_key": [1, "CB3688B7561D488A2A4834E1AEE9398BEF94844D8BDBBCA980C11E3654A45906"], + "bond_height": 0, + "unbond_height": 0, + "last_commit_height": 0, + "voting_power": 5000000000, + "accum": 0 + }], + "proposal": null + }, + "validators": { + "block_height": 0, + "bonded_validators": [{ + "address": "37236DF251AB70022B1DA351F08A20FB52443E37", + "pub_key": [1, "CB3688B7561D488A2A4834E1AEE9398BEF94844D8BDBBCA980C11E3654A45906"], + "bond_height": 0, + "unbond_height": 0, + "last_commit_height": 0, + "voting_power": 5000000000, + "accum": 0 + }], + "unbonding_validators": [] + }, + "network_info": { + "moniker": "anothertester", + "listening": false, + "listeners": [], + "peers": [] + }, + "moniker": { + "moniker": "anothertester" + }, + "listening": { + "listening": false + }, + "listeners": { + "listeners": [] + }, + "peers": [], + "tx_create_receipt": { + "tx_hash": "C1C84BCD4CCA6D6132D1E702FA4A7618DBCDB52F", + "creates_contract": 1, + "contract_addr": "9FC1ECFCAE2A554D4D1A000D0D80F748E66359E3" + }, + "tx_receipt": { + "tx_hash": "A40873D4C7136F6D79476A035D4265781FC20A3B", + "creates_contract": 0, + "contract_addr": "" + }, + "unconfirmed_txs": { + "txs": [ + [ 2, { + "input": { + "address": "37236DF251AB70022B1DA351F08A20FB52443E37", + "amount": 1000, + "sequence": 1, + "signature": [ 1, "39E1D98C2F4F8FC5A98442C55DCC8FCBCE4ADB0F6BAD5C5258CEFE94EFB0315EA9616CC275F97E4D04C5A8FD08D73B84A28B7CFEAEE98F4A37E2F2BCA1830907" ], + "pub_key": [1, "CB3688B7561D488A2A4834E1AEE9398BEF94844D8BDBBCA980C11E3654A45906"] + }, + "address": "", + "gas_limit": 1000, + "fee": 1000, + "data": "5B33600060006101000A81548173FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF021916908302179055505B6102828061003B6000396000F3006000357C01000000000000000000000000000000000000000000000000000000009004806337F428411461004557806340C10F191461005A578063D0679D341461006E57005B610050600435610244565B8060005260206000F35B610068600435602435610082565B60006000F35B61007C600435602435610123565B60006000F35B600060009054906101000A900473FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1673FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF163373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1614156100DD576100E2565B61011F565B80600160005060008473FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1681526020019081526020016000206000828282505401925050819055505B5050565B80600160005060003373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF168152602001908152602001600020600050541061015E57610163565B610240565B80600160005060003373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16815260200190815260200160002060008282825054039250508190555080600160005060008473FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1681526020019081526020016000206000828282505401925050819055507F93EB3C629EB575EDAF0252E4F9FC0C5CCADA50496F8C1D32F0F93A65A8257EB560003373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1681526020018373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1681526020018281526020016000A15B5050565B6000600160005060008373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16815260200190815260200160002060005054905061027D565B91905056" + } ], + [ 2, { + "input": { + "address": "37236DF251AB70022B1DA351F08A20FB52443E37", + "amount": 1000, + "sequence": 3, + "signature": [1, "8D84089EC1140C5AF474DB7E764E937D9C6309BA0AD7BCC56108A2075504005AE2EE1AD71C3D414F9D793D2BFAD77C9572D9494736E6F3D1A62D17DF4A01090D" ], + "pub_key": null + }, + "address": "9FC1ECFCAE2A554D4D1A000D0D80F748E66359E3", + "gas_limit": 1000, + "fee": 1000, + "data": "" + } ] + ]}, + "call_code": { + "return": "6000357c01000000000000000000000000000000000000000000000000000000009004806337f428411461004557806340c10f191461005a578063d0679d341461006e57005b610050600435610244565b8060005260206000f35b610068600435602435610082565b60006000f35b61007c600435602435610123565b60006000f35b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156100dd576100e2565b61011f565b80600160005060008473ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828282505401925050819055505b5050565b80600160005060003373ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600050541061015e57610163565b610240565b80600160005060003373ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282825054039250508190555080600160005060008473ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828282505401925050819055507f93eb3c629eb575edaf0252e4f9fc0c5ccada50496f8c1d32f0f93a65a8257eb560003373ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020016000a15b5050565b6000600160005060008373ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060005054905061027d565b91905056", + "gas_used": 0 + }, + "accounts": { + "accounts": [ + { + "address": "0000000000000000000000000000000000000002", + "pub_key": null, + "sequence": 0, + "balance": 565000000000, + "code": "", + "storage_root": "" + }, + { + "address": "0000000000000000000000000000000000000004", + "pub_key": null, + "sequence": 0, + "balance": 110000000000, + "code": "", + "storage_root": "" + }, + { + "address": "37236DF251AB70022B1DA351F08A20FB52443E37", + "pub_key": null, + "sequence": 0, + "balance": 110000000000, + "code": "", + "storage_root": "" + }, + { + "address": "9E54C9ECA9A3FD5D4496696818DA17A9E17F69DA", + "pub_key": null, + "sequence": 0, + "balance": 525000000000, + "code": "", + "storage_root": "" + }, + { + "address": "F81CB9ED0A868BD961C4F5BBC0E39B763B89FCB6", + "pub_key": null, + "sequence": 0, + "balance": 690000000000, + "code": "", + "storage_root": "" + } + + ] + }, + "account": { + "address": "9FC1ECFCAE2A554D4D1A000D0D80F748E66359E3", + "pub_key": null, + "sequence": 0, + "balance": 0, + "code": "", + "storage_root": "" + }, + "storage": { + "storage_root": "", + "storage_items": [] + }, + "storage_at": {}, + "blockchain_info": { + "chain_id": "my_tests", + "genesis_hash": "DA4F4DC4A54620F1E0AA1213631C4DC2957B7415E3F8C066C30009BC57C4E5FC", + "latest_block_height": 0, + "latest_block": null + }, + "chain_id": { + "chain_id": "my_tests" + }, + "genesis_hash": { + "hash": "DA4F4DC4A54620F1E0AA1213631C4DC2957B7415E3F8C066C30009BC57C4E5FC" + }, + "latest_block_height": { + "height": 0 + }, + "block": null, + "blocks": { + "min_height": 0, + "max_height": 0, + "block_metas": [] + } + } +}` + +var serverDuration uint = 100 + +type ( + BlockRange struct { + Min int `json:"min"` + Max int `json:"max"` + } +) + +type ( + ChainData struct { + PrivValidator *state.PrivValidator `json:"priv_validator"` + Genesis *state.GenesisDoc `json:"genesis"` + } + + Input struct { + AccountAddress string `json:"account_address"` + StorageAddress string `json:"storage_address"` + TxCreate *edb.TransactParam `json:"tx_create"` + Tx *edb.TransactParam `json:"tx"` + CallCode *edb.CallCodeParam `json:"call_code"` + BlockRange *BlockRange `json:"block_range"` + } + + Output struct { + ConsensusState *ep.ConsensusState `json:"consensus_state"` + Validators *ep.ValidatorList `json:"validators"` + NetworkInfo *ep.NetworkInfo `json:"network_info"` + Moniker *ep.Moniker `json:"moniker"` + Listening *ep.Listening `json:"listening"` + Listeners *ep.Listeners `json:"listeners"` + Peers []*ep.Peer `json:"peers"` + TxCreateReceipt *ep.Receipt `json:"tx_create_receipt"` + TxReceipt *ep.Receipt `json:"tx_receipt"` + UnconfirmedTxs *ep.UnconfirmedTxs `json:"unconfirmed_txs"` + CallCode *ep.Call `json:"call_code"` + Accounts *ep.AccountList `json:"accounts"` + Account *account.Account `json:"account"` + Storage *ep.Storage `json:"storage"` + StorageAt *ep.StorageItem `json:"storage_at"` + BlockchainInfo *ep.BlockchainInfo `json:"blockchain_info"` + ChainId *ep.ChainId `json:"chain_id"` + GenesisHash *ep.GenesisHash `json:"genesis_hash"` + LatestBlockHeight *ep.LatestBlockHeight `json:"latest_block_height"` + Block *types.Block `json:"block"` + Blocks *ep.Blocks `json:"blocks"` + } + + TestData struct { + ChainData *ChainData `json:"chain_data"` + Input *Input `json:"input"` + Output *Output `json:"output"` + } +) + +func LoadTestData() *TestData { + codec := edb.NewTCodec() + testData := &TestData{} + err := codec.DecodeBytes(testData, []byte(testDataJson)) + // TODO for now. + if err != nil { + panic(err) + } + return testData +} diff --git a/test/web_api_test.go b/test/web_api_test.go new file mode 100644 index 0000000000000000000000000000000000000000..5fd560696703bbfb2e4f8b6e1f756bb6b386061a --- /dev/null +++ b/test/web_api_test.go @@ -0,0 +1,261 @@ +package test + +// Basic imports +import ( + "bytes" + "fmt" + // edb "github.com/eris-ltd/erisdb/erisdb" + "github.com/tendermint/tendermint/account" + ess "github.com/eris-ltd/erisdb/erisdb/erisdbss" + edb "github.com/eris-ltd/erisdb/erisdb" + ep "github.com/eris-ltd/erisdb/erisdb/pipe" + "github.com/eris-ltd/erisdb/rpc" + "github.com/eris-ltd/erisdb/server" + "github.com/gin-gonic/gin" + "github.com/stretchr/testify/suite" + "net/http" + "os" + "path" + "testing" + "time" +) + +const SS_URL = "http://localhost:1337/server" +const SERVER_DURATION = 5; + +// +type WebApiSuite struct { + suite.Suite + baseDir string + serveProcess *server.ServeProcess + codec rpc.Codec + sUrl string + testData *TestData +} + +func (this *WebApiSuite) SetupSuite() { + gin.SetMode(gin.ReleaseMode) + baseDir := path.Join(os.TempDir(), "/.edbservers") + ss := ess.NewServerServer(baseDir) + proc := server.NewServeProcess(nil, ss) + _ = proc.Start() + this.serveProcess = proc + time.Sleep(1*time.Second) + testData := LoadTestData() + this.codec = edb.NewTCodec() + + requestData := &ess.RequestData{testData.ChainData.PrivValidator, testData.ChainData.Genesis, SERVER_DURATION} + rBts, _ := this.codec.EncodeBytes(requestData) + resp, _ := http.Post(SS_URL, "application/json", bytes.NewBuffer(rBts)) + rd := &ess.ResponseData{} + _ = this.codec.Decode(rd, resp.Body) + fmt.Println("Received URL: " + rd.URL) + this.sUrl = rd.URL + this.testData = testData + time.Sleep(1*time.Second) +} + +func (this *WebApiSuite) TearDownSuite() { + sec := this.serveProcess.StopEventChannel() + this.serveProcess.Stop(time.Millisecond) + <-sec + os.RemoveAll(this.baseDir) +} + +// ********************************************* Consensus ********************************************* + +func (this *WebApiSuite) Test_A0_ConsensusState() { + resp := this.get("/consensus") + ret := &ep.ConsensusState{} + errD := this.codec.Decode(ret, resp.Body) + this.NoError(errD) + ret.StartTime = "" + this.Equal(ret, this.testData.Output.ConsensusState) +} + +func (this *WebApiSuite) Test_A1_Validators() { + resp := this.get("/consensus/validators") + ret := &ep.ValidatorList{} + errD := this.codec.Decode(ret, resp.Body) + this.NoError(errD) + this.Equal(ret, this.testData.Output.Validators) +} + +// ********************************************* Network ********************************************* + +func (this *WebApiSuite) Test_B0_NetworkInfo() { + resp := this.get("/network") + ret := &ep.NetworkInfo{} + errD := this.codec.Decode(ret, resp.Body) + this.NoError(errD) + this.Equal(ret, this.testData.Output.NetworkInfo) +} + +func (this *WebApiSuite) Test_B1_Moniker() { + resp := this.get("/network/moniker") + ret := &ep.Moniker{} + errD := this.codec.Decode(ret, resp.Body) + this.NoError(errD) + this.Equal(ret, this.testData.Output.Moniker) +} + +func (this *WebApiSuite) Test_B2_Listening() { + resp := this.get("/network/listening") + ret := &ep.Listening{} + errD := this.codec.Decode(ret, resp.Body) + this.NoError(errD) + this.Equal(ret, this.testData.Output.Listening) +} + +func (this *WebApiSuite) Test_B3_Listeners() { + resp := this.get("/network/listeners") + ret := &ep.Listeners{} + errD := this.codec.Decode(ret, resp.Body) + this.NoError(errD) + this.Equal(ret, this.testData.Output.Listeners) +} + +func (this *WebApiSuite) Test_B4_Peers() { + resp := this.get("/network/peers") + ret := []*ep.Peer{} + errD := this.codec.Decode(ret, resp.Body) + this.NoError(errD) + this.Equal(ret, this.testData.Output.Peers) +} + +// ********************************************* Transactions ********************************************* + +func (this *WebApiSuite) Test_C0_TxCreate() { + resp := this.postJson("/unsafe/txpool", this.testData.Input.TxCreate) + ret := &ep.Receipt{} + errD := this.codec.Decode(ret, resp.Body) + this.NoError(errD) + this.Equal(ret, this.testData.Output.TxCreateReceipt) +} + +func (this *WebApiSuite) Test_C1_Tx() { + resp := this.postJson("/unsafe/txpool", this.testData.Input.Tx) + ret := &ep.Receipt{} + errD := this.codec.Decode(ret, resp.Body) + this.NoError(errD) + this.Equal(ret, this.testData.Output.TxReceipt) +} + +func (this *WebApiSuite) Test_C2_UnconfirmedTxs() { + resp := this.get("/txpool") + ret := &ep.UnconfirmedTxs{} + errD := this.codec.Decode(ret, resp.Body) + this.NoError(errD) + this.Equal(ret, this.testData.Output.UnconfirmedTxs) +} + +func (this *WebApiSuite) Test_C3_CallCode() { + resp := this.postJson("/calls", this.testData.Input.CallCode) + ret := &ep.Call{} + errD := this.codec.Decode(ret, resp.Body) + this.NoError(errD) + this.Equal(ret, this.testData.Output.CallCode) +} + +// ********************************************* Accounts ********************************************* + +func (this *WebApiSuite) Test_D0_Accounts() { + resp := this.get("/accounts") + ret := &ep.AccountList{} + errD := this.codec.Decode(ret, resp.Body) + this.NoError(errD) + this.Equal(ret, this.testData.Output.Accounts) +} + +func (this *WebApiSuite) Test_D1_Account() { + resp := this.get("/accounts/" + this.testData.Input.AccountAddress) + ret := &account.Account{} + errD := this.codec.Decode(ret, resp.Body) + this.NoError(errD) + this.Equal(ret, this.testData.Output.Account) +} + +func (this *WebApiSuite) Test_D2_Storage() { + resp := this.get("/accounts/" + this.testData.Input.AccountAddress + "/storage") + ret := &ep.Storage{} + errD := this.codec.Decode(ret, resp.Body) + this.NoError(errD) + this.Equal(ret, this.testData.Output.Storage) +} + +func (this *WebApiSuite) Test_D3_StorageAt() { + addr := this.testData.Input.AccountAddress + key := this.testData.Input.StorageAddress + resp := this.get("/accounts/" + addr + "/storage/" + key) + ret := &ep.StorageItem{} + errD := this.codec.Decode(ret, resp.Body) + this.NoError(errD) + this.Equal(ret, this.testData.Output.StorageAt) +} + +// ********************************************* Blockchain ********************************************* + +func (this *WebApiSuite) Test_E0_BlockchainInfo() { + resp := this.get("/blockchain") + ret := &ep.BlockchainInfo{} + errD := this.codec.Decode(ret, resp.Body) + this.NoError(errD) + this.Equal(ret, this.testData.Output.BlockchainInfo) +} + +func (this *WebApiSuite) Test_E1_ChainId() { + resp := this.get("/blockchain/chain_id") + ret := &ep.ChainId{} + errD := this.codec.Decode(ret, resp.Body) + this.NoError(errD) + this.Equal(ret, this.testData.Output.ChainId) +} + +func (this *WebApiSuite) Test_E2_GenesisHash() { + resp := this.get("/blockchain/genesis_hash") + ret := &ep.GenesisHash{} + errD := this.codec.Decode(ret, resp.Body) + this.NoError(errD) + this.Equal(ret, this.testData.Output.GenesisHash) +} + +func (this *WebApiSuite) Test_E3_LatestBlockHeight() { + resp := this.get("/blockchain/latest_block_height") + ret := &ep.LatestBlockHeight{} + errD := this.codec.Decode(ret, resp.Body) + this.NoError(errD) + this.Equal(ret, this.testData.Output.LatestBlockHeight) +} + +func (this *WebApiSuite) Test_E4_Blocks() { + br := this.testData.Input.BlockRange + resp := this.get(fmt.Sprintf("/blockchain/blocks?q=height:%d..%d", br.Min, br.Max)) + ret := &ep.Blocks{} + errD := this.codec.Decode(ret, resp.Body) + this.NoError(errD) + this.Equal(ret, this.testData.Output.Blocks) +} + +// ********************************************* Utilities ********************************************* + +func (this *WebApiSuite) get(endpoint string) *http.Response { + resp, errG := http.Get(this.sUrl + endpoint) + this.NoError(errG) + this.Equal(200, resp.StatusCode) + return resp +} + +func (this *WebApiSuite) postJson(endpoint string, v interface{}) *http.Response { + bts, errE := this.codec.EncodeBytes(v) + this.NoError(errE) + resp, errP := http.Post(this.sUrl + endpoint, "application/json", bytes.NewBuffer(bts)) + this.NoError(errP) + this.Equal(200, resp.StatusCode) + return resp +} + +// ********************************************* Entrypoint ********************************************* + +func TestWebApiSuite(t *testing.T) { + suite.Run(t, &WebApiSuite{}) +} \ No newline at end of file diff --git a/test/ws_flood_test.go b/test/ws_flood_test.go index a85ca1d02ed6e895350ebff506cdef20ae270000..9c2ed710627439bf167be8679179e4ec7b95ee0c 100644 --- a/test/ws_flood_test.go +++ b/test/ws_flood_test.go @@ -59,8 +59,9 @@ func TestWsFlooding(t *testing.T) { t.Logf("Flooding...") // Run. Blocks. errRun := runWs() - - errStop := serveProcess.Stop(time.Millisecond * 100) + stopC := serveProcess.StopEventChannel() + errStop := serveProcess.Stop(0) + <-stopC assert.NoError(t, errRun, "ScumSocketed!") assert.NoError(t, errStop, "ScumSocketed!") o, c, a := sc.Report()