diff --git a/erisdb/erisdbss/http.go b/erisdb/erisdbss/http.go index da3df60e113451e11860bc947b3a9ecfa30bc5dd..b1ad26a76025a15d68292c67555ed43ea83147a5 100644 --- a/erisdb/erisdbss/http.go +++ b/erisdb/erisdbss/http.go @@ -21,6 +21,7 @@ fast_sync = false db_backend = "leveldb" log_level = "debug" node_laddr = "" +rpc_laddr = "" ` // User data accepts a private validator and genesis json object. diff --git a/erisdb/methods.go b/erisdb/methods.go index be9e49f77a462a1d825931b16b62add739f5afeb..d3be7483c5d29e9f8e3bdc2aac72546b3a4415fa 100644 --- a/erisdb/methods.go +++ b/erisdb/methods.go @@ -351,9 +351,10 @@ func (this *ErisDbMethods) Call(request *rpc.RPCRequest, requester interface{}) if err != nil { return nil, rpc.INVALID_PARAMS, err } - address := param.Address + from := param.From + to := param.Address data := param.Data - call, errC := this.pipe.Transactor().Call(address, data) + call, errC := this.pipe.Transactor().Call(from, to, data) if errC != nil { return nil, rpc.INTERNAL_ERROR, errC } @@ -366,9 +367,10 @@ func (this *ErisDbMethods) CallCode(request *rpc.RPCRequest, requester interface if err != nil { return nil, rpc.INVALID_PARAMS, err } + from := param.From code := param.Code data := param.Data - call, errC := this.pipe.Transactor().CallCode(code, data) + call, errC := this.pipe.Transactor().CallCode(from, code, data) if errC != nil { return nil, rpc.INTERNAL_ERROR, errC } diff --git a/erisdb/params.go b/erisdb/params.go index 785e716d7aebc95de84b6e8266ea7879e8d0f2b0..eb1db8d808a03015a8c9e68ba38283eff964c356 100644 --- a/erisdb/params.go +++ b/erisdb/params.go @@ -19,7 +19,7 @@ type ( AccountsParam struct { Filters []*pipe.FilterData `json:"filters"` } - + // Used to send an address FilterListParam struct { Filters []*pipe.FilterData `json:"filters"` @@ -63,11 +63,13 @@ type ( // Used when doing calls CallParam struct { Address []byte `json:"address"` + From []byte `json:"from"` Data []byte `json:"data"` } // Used when doing code calls CallCodeParam struct { + From []byte `json:"from"` Code []byte `json:"code"` Data []byte `json:"data"` } @@ -87,7 +89,7 @@ type ( Fee int64 `json:"fee"` GasLimit int64 `json:"gas_limit"` } - + NameRegEntryParam struct { Name string `json:"name"` } @@ -101,5 +103,4 @@ type ( Fee int64 `json:"fee"` Amount int64 `json:"amount"` } - ) diff --git a/erisdb/pipe/pipe.go b/erisdb/pipe/pipe.go index b4c4aa198b77b929363406f7d4a3cc571ed2ad36..340aa9257cda12b093a6d8a82ebda59b8d3ec26f 100644 --- a/erisdb/pipe/pipe.go +++ b/erisdb/pipe/pipe.go @@ -66,8 +66,8 @@ type ( } Transactor interface { - Call(address, data []byte) (*Call, error) - CallCode(code, data []byte) (*Call, error) + Call(fromAddress, toAddress, data []byte) (*Call, error) + CallCode(fromAddress, code, data []byte) (*Call, error) BroadcastTx(tx types.Tx) (*Receipt, error) Transact(privKey, address, data []byte, gasLimit, fee int64) (*Receipt, error) TransactNameReg(privKey []byte, name, data string, amount, fee int64) (*Receipt, error) diff --git a/erisdb/pipe/transactor.go b/erisdb/pipe/transactor.go index 2a08f65392498b0f93057c5a33cec8660eb4956d..91089a0446c0106991039d65343be1322625fc5e 100644 --- a/erisdb/pipe/transactor.go +++ b/erisdb/pipe/transactor.go @@ -38,16 +38,19 @@ func newTransactor(eventSwitch tEvents.Fireable, consensusState *cs.ConsensusSta // Run a contract's code on an isolated and unpersisted state // Cannot be used to create new contracts -func (this *transactor) Call(address, data []byte) (*Call, error) { +func (this *transactor) Call(fromAddress, toAddress, data []byte) (*Call, error) { st := this.consensusState.GetState() // performs a copy cache := state.NewBlockCache(st) - outAcc := cache.GetAccount(address) + outAcc := cache.GetAccount(toAddress) if outAcc == nil { - return nil, fmt.Errorf("Account %x does not exist", address) + return nil, fmt.Errorf("Account %X does not exist", toAddress) + } + if fromAddress == nil { + fromAddress = []byte{} } callee := toVMAccount(outAcc) - caller := &vm.Account{Address: cmn.Zero256} + caller := &vm.Account{Address: cmn.LeftPadWord256(fromAddress)} txCache := state.NewTxCache(cache) params := vm.Params{ BlockHeight: int64(st.LastBlockHeight), @@ -68,12 +71,14 @@ func (this *transactor) Call(address, data []byte) (*Call, error) { // Run the given code on an isolated and unpersisted state // Cannot be used to create new contracts. -func (this *transactor) CallCode(code, data []byte) (*Call, error) { - +func (this *transactor) CallCode(fromAddress, code, data []byte) (*Call, error) { + if fromAddress == nil { + fromAddress = []byte{} + } st := this.consensusState.GetState() // performs a copy cache := this.mempoolReactor.Mempool.GetCache() - callee := &vm.Account{Address: cmn.Zero256} - caller := &vm.Account{Address: cmn.Zero256} + callee := &vm.Account{Address: cmn.LeftPadWord256(fromAddress)} + caller := &vm.Account{Address: cmn.LeftPadWord256(fromAddress)} txCache := state.NewTxCache(cache) params := vm.Params{ BlockHeight: int64(st.LastBlockHeight), diff --git a/erisdb/restServer.go b/erisdb/restServer.go index df9335799991a46f41555b070b9b0a56904fde96..96ad35e08566436531ebeb0994e0419bd4cb4289 100644 --- a/erisdb/restServer.go +++ b/erisdb/restServer.go @@ -401,7 +401,7 @@ func (this *RestServer) handleCall(c *gin.Context) { if errD != nil { c.AbortWithError(500, errD) } - call, err := this.pipe.Transactor().Call(param.Address, param.Data) + call, err := this.pipe.Transactor().Call(param.From, param.Address, param.Data) if err != nil { c.AbortWithError(500, err) } @@ -415,7 +415,7 @@ func (this *RestServer) handleCallCode(c *gin.Context) { if errD != nil { c.AbortWithError(500, errD) } - call, err := this.pipe.Transactor().CallCode(param.Code, param.Data) + call, err := this.pipe.Transactor().CallCode(param.From, param.Code, param.Data) if err != nil { c.AbortWithError(500, err) } diff --git a/erisdb/serve.go b/erisdb/serve.go index 462db42735dacc4b92df0293dd16a3f51445a169..7078f9a280a710d731a63ab08ade309588115f9b 100644 --- a/erisdb/serve.go +++ b/erisdb/serve.go @@ -14,7 +14,7 @@ import ( "path" ) -const ERISDB_VERSION = "0.11.0" +const ERISDB_VERSION = "0.11.1" const TENDERMINT_VERSION = "0.5.0" var log = log15.New("module", "eris/erisdb_server") @@ -79,7 +79,7 @@ func ServeErisDB(workDir string) (*server.ServeProcess, error) { return proc, nil } -// Private. Create a new node +// Private. Create a new node. func startNode(nd *node.Node, ready chan struct{}, shutDown <-chan struct{}) { laddr := tmConfig.GetString("node_laddr") if laddr != "" { @@ -94,7 +94,10 @@ func startNode(nd *node.Node, ready chan struct{}, shutDown <-chan struct{}) { if len(tmConfig.GetString("seeds")) > 0 { nd.DialSeed() } - + + if len(tmConfig.GetString("rpc_laddr")) > 0 { + nd.StartRPC() + } ready <- struct{}{} // Block until everything is shut down. <-shutDown diff --git a/server/README.md b/server/README.md new file mode 100644 index 0000000000000000000000000000000000000000..a94b4c5f27ff52e17e40751c97fef81ecec5f2d6 --- /dev/null +++ b/server/README.md @@ -0,0 +1,33 @@ +# Server + +This package contains classes for starting and running HTTP and websocket servers. + +## Server interface + +Servers implements the `Server` interface. A 'ServerConfig' and 'gin.Engine' object is supplied in the 'Start' method, so that they may set themselves up and set up the routes etc. + +``` +type Server interface { + Start(*ServerConfig, *gin.Engine) + Running() bool + ShutDown() +} +``` + +The `Server` interface can be found in `server.go`. + +## ServeProcess + +The `ServeProcess` does the port binding and listening. You may attach any number of servers to the serve-process, and it will automatically call their 'Start' and 'ShutDown' methods when starting up and shutting down. You may also attach start and shutdown listeners to the `ServeProcess`. + +The `ServeProcess` class can be found in `server.go`. + +## WebSocketServer + +The `WebSocketServer` is a template for servers that use websocket connections rather then HTTP. It will + +## Config + +The config assumes that there is a default HTTP and Websocket server for RPC, and some other fields. See the main README.md for details. + +While the system is generic (i.e. it does not care what a `Server` is or does), the configuration file is not. The reason is that the server is written specifically for eris-db, and I do not want to manage generic config files (or perhaps even one per server). \ No newline at end of file diff --git a/test/mock/pipe.go b/test/mock/pipe.go index 16ab4a75b022955c757bc028b52d587c7efba70e..9e2837be997ce4221f139dc2f993b5db7155726b 100644 --- a/test/mock/pipe.go +++ b/test/mock/pipe.go @@ -218,11 +218,11 @@ type transactor struct { testData *td.TestData } -func (this *transactor) Call(address, data []byte) (*ep.Call, error) { +func (this *transactor) Call(fromAddress, toAddress, data []byte) (*ep.Call, error) { return this.testData.Call.Output, nil } -func (this *transactor) CallCode(code, data []byte) (*ep.Call, error) { +func (this *transactor) CallCode(from, code, data []byte) (*ep.Call, error) { return this.testData.CallCode.Output, nil } diff --git a/test/pipe/pipe_test.go b/test/pipe/pipe_test.go new file mode 100644 index 0000000000000000000000000000000000000000..59c0117912e743a056520eb7fee848494b6ab993 --- /dev/null +++ b/test/pipe/pipe_test.go @@ -0,0 +1 @@ +package pipe \ No newline at end of file diff --git a/test/testdata/helpers.go b/test/testdata/helpers.go new file mode 100644 index 0000000000000000000000000000000000000000..d3943838cb746bacca996da7b8057851a94ed71b --- /dev/null +++ b/test/testdata/helpers.go @@ -0,0 +1,88 @@ +package testdata + +import ( + "fmt" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/binary" + . "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state" + "github.com/eris-ltd/eris-db/files" + "github.com/eris-ltd/eris-db/server" + "os" + "path" +) + +const TendermintConfigDefault = `# This is a TOML config file. +# For more information, see https://github.com/toml-lang/toml + +moniker = "__MONIKER__" +seeds = "" +fast_sync = false +db_backend = "leveldb" +log_level = "debug" +node_laddr = "" +rpc_laddr = "" +` + +func CreateTempWorkDir(privValidator *state.PrivValidator, genesis *state.GenesisDoc, folderName string) (string, error) { + + workDir := path.Join(os.TempDir(), folderName) + os.RemoveAll(workDir) + errED := EnsureDir(workDir) + + if errED != nil { + return "", errED + } + + cfgName := path.Join(workDir, "config.toml") + scName := path.Join(workDir, "server_conf.toml") + pvName := path.Join(workDir, "priv_validator.json") + genesisName := path.Join(workDir, "genesis.json") + + // Write config. + errCFG := files.WriteFileRW(cfgName, []byte(TendermintConfigDefault)) + if errCFG != nil { + return "", errCFG + } + fmt.Printf("File written: %s\n.", cfgName) + + // Write validator. + errPV := writeJSON(pvName, privValidator) + if errPV != nil { + return "", errPV + } + fmt.Printf("File written: %s\n.", pvName) + + // Write genesis + errG := writeJSON(genesisName, genesis) + if errG != nil { + return "", errG + } + fmt.Printf("File written: %s\n.", genesisName) + + // Write server config. + errWC := server.WriteServerConfig(scName, server.DefaultServerConfig()) + if errWC != nil { + return "", errWC + } + fmt.Printf("File written: %s\n.", scName) + return workDir, nil +} + +// Used to write json files using tendermints binary package. +func writeJSON(file string, v interface{}) error { + var n int64 + var errW error + fo, errC := os.Create(file) + if errC != nil { + return errC + } + binary.WriteJSON(v, fo, &n, &errW) + if errW != nil { + return errW + } + errL := fo.Close() + if errL != nil { + return errL + } + return nil +} diff --git a/test/testdata/testdata/testdata.go b/test/testdata/testdata/testdata.go index 03c433657c8354964777c2c1587020798efb43ea..eb1a799b7a4248b6e1f21aaecc5c1c888fcaa328 100644 --- a/test/testdata/testdata/testdata.go +++ b/test/testdata/testdata/testdata.go @@ -417,6 +417,7 @@ var testDataJson = `{ }, "CallCode": { "input": { + "from": "DEADBEEF", "code": "5B33600060006101000A81548173FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF021916908302179055505B6102828061003B6000396000F3006000357C01000000000000000000000000000000000000000000000000000000009004806337F428411461004557806340C10F191461005A578063D0679D341461006E57005B610050600435610244565B8060005260206000F35B610068600435602435610082565B60006000F35B61007C600435602435610123565B60006000F35B600060009054906101000A900473FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1673FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF163373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1614156100DD576100E2565B61011F565B80600160005060008473FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1681526020019081526020016000206000828282505401925050819055505B5050565B80600160005060003373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF168152602001908152602001600020600050541061015E57610163565B610240565B80600160005060003373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16815260200190815260200160002060008282825054039250508190555080600160005060008473FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1681526020019081526020016000206000828282505401925050819055507F93EB3C629EB575EDAF0252E4F9FC0C5CCADA50496F8C1D32F0F93A65A8257EB560003373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1681526020018373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1681526020018281526020016000A15B5050565B6000600160005060008373FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16815260200190815260200160002060005054905061027D565B91905056", "data": "" }, @@ -426,7 +427,7 @@ var testDataJson = `{ } }, "Call": { - "input": {"address": "9FC1ECFCAE2A554D4D1A000D0D80F748E66359E3", "data": ""}, + "input": {"address": "9FC1ECFCAE2A554D4D1A000D0D80F748E66359E3", "from": "DEADBEEF", "data": ""}, "output": { "return": "6000357c01000000000000000000000000000000000000000000000000000000009004806337f428411461004557806340c10f191461005a578063d0679d341461006e57005b610050600435610244565b8060005260206000f35b610068600435602435610082565b60006000f35b61007c600435602435610123565b60006000f35b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156100dd576100e2565b61011f565b80600160005060008473ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828282505401925050819055505b5050565b80600160005060003373ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600050541061015e57610163565b610240565b80600160005060003373ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282825054039250508190555080600160005060008473ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828282505401925050819055507f93eb3c629eb575edaf0252e4f9fc0c5ccada50496f8c1d32f0f93a65a8257eb560003373ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020016000a15b5050565b6000600160005060008373ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060005054905061027d565b91905056", "gas_used": 0