diff --git a/README.md b/README.md index bd74638527dcdb4fccf3f58113f77f295b3660df..ff5c306c1dcb2eed05a03e348ce530b82033e7ce 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -# Eris DB +# Eris-DB |[](https://godoc.org/github.com/eris-ltd/eris-db) | Linux | |---|-------| | Master | [](https://circleci.com/gh/eris-ltd/eris-db/tree/master) | | Develop | [](https://circleci.com/gh/eris-ltd/eris-db/tree/develop) | -Eris DB is Eris' blockchain client. It includes a permissions layer, an implementation of the Ethereum Virtual Machine, and uses Tendermint Consensus. Most functionality is provided by `eris chains`, exposed through [eris-cli](https://monax.io/docs/documentation/cli), the entry point for the Eris Platform. +Eris-db is Monax' permissioned blockchain client. It executes Ethereum smart contracts on a permissioned virtual machine. Eris-db provides transaction finality and high transaction throughput on proof-of-stake Tendermint consensus engine. For smart contract development most functionality is provided by `eris chains`, exposed through [eris](https://monax.io/docs/documentation/cli), the entry point for the Eris Platform. ## Table of Contents @@ -22,7 +22,7 @@ See the [eris-db documentation](https://monax.io/docs/documentation/db/) for mor ## Installation -`eris-db` is intended to be used by the `eris chains` command via [eris-cli](https://monax.io/docs/documentation/cli/latest/eris_chains). Available commands such as `make | start | stop | logs | inspect | update` are used for chain lifecycle management. +`eris-db` is intended to be used by the `eris chains` command via [eris](https://monax.io/docs/documentation/cli/latest/eris_chains). Available commands such as `make | start | stop | logs | inspect | update` are used for chain lifecycle management. ### For Developers Dependency management for eris-db is managed with [glide](github.com/Masterminds/glide), and you can build eris-db from source by following @@ -32,9 +32,13 @@ Dependency management for eris-db is managed with [glide](github.com/Masterminds 3. and execute following commands in a terminal: ``` go get github.com/Masterminds/glide + go get -d github.com/eris-ltd/eris-db + REPO=$($GOPATH/src/github.com/eris-ltd/eris-db) + cd $REPO && glide install + cd $REPO/cmd/eris-db && go install ``` diff --git a/rpc/codec.go b/rpc/codec.go index bbf0ba604183cc0da6be98b0c0909181c9ba9773..750a5a88e8a6ea672fe635ef41c2f69d2c36274d 100644 --- a/rpc/codec.go +++ b/rpc/codec.go @@ -23,5 +23,6 @@ type Codec interface { EncodeBytes(interface{}) ([]byte, error) Encode(interface{}, io.Writer) error DecodeBytes(interface{}, []byte) error + DecodeBytesPtr(interface{}, []byte) error Decode(interface{}, io.Reader) error } diff --git a/rpc/v0/codec.go b/rpc/v0/codec.go index 5763c7bc710adfcc897cb581a25da5596026f27c..344c1c98f12977352419dcd1247659b0de59e4ec 100644 --- a/rpc/v0/codec.go +++ b/rpc/v0/codec.go @@ -45,6 +45,8 @@ func (this *TCodec) EncodeBytes(v interface{}) ([]byte, error) { return wire.JSONBytes(v), nil } +// TODO: [ben] implement EncodeBytesPtr ? + // Decode from an io.Reader. func (this *TCodec) Decode(v interface{}, r io.Reader) error { bts, errR := ioutil.ReadAll(r) @@ -62,3 +64,10 @@ func (this *TCodec) DecodeBytes(v interface{}, bts []byte) error { wire.ReadJSON(v, bts, &err) return err } + +// Decode from a byte array pointer. +func (this *TCodec) DecodeBytesPtr(v interface{}, bts []byte) error { + var err error + wire.ReadJSONPtr(v, bts, &err) + return err +} diff --git a/rpc/v0/json_service_data_test.go b/rpc/v0/json_service_data_test.go new file mode 100644 index 0000000000000000000000000000000000000000..96be04138a4d5399650a4ae00570049754600b88 --- /dev/null +++ b/rpc/v0/json_service_data_test.go @@ -0,0 +1,71 @@ +// Copyright 2017 Monax Industries Limited +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rpc_v0 + +import ( + "encoding/json" + "testing" + + "github.com/eris-ltd/eris-db/rpc" + "github.com/eris-ltd/eris-db/txs" + + "github.com/stretchr/testify/assert" +) + +var testBroadcastCallTxJsonRequest = []byte(` +{ + "id": "57EC1D39-7B3D-4F96-B286-8FC128177AFC4", + "jsonrpc": "2.0", + "method": "erisdb.broadcastTx", + "params": [ + 2, + { + "address": "5A9083BB0EFFE4C8EB2ADD29174994F73E77D418", + "data": "2F2397A00000000000000000000000000000000000000000000000000000000000003132", + "fee": 1, + "gas_limit": 1000000, + "input": { + "address": "BE18FDCBF12BF99F4D75325E17FF2E78F1A35FE8", + "amount": 1, + "pub_key": [ + 1, + "8D1611925948DC2EDDF739FB65CE517757D286155A039B28441C3349BE9A8C38" + ], + "sequence": 2, + "signature": [ + 1, + "B090D622F143ECEDA9B9E7B15485CE7504453C05434951CF867B013D80ED1BD2A0CA32846FC175D234CDFB9D5C3D792759E8FE79FD4DB3006B24950EE3C37D00" + ] + } + } + ] +}`) + +// strictly test the codec for go-wire encoding of the Json format, +// This should restore compatibility with the format on v0.11.4 +// (which was broken on v0.12) +func TestCallTxJsonFormatCodec(t *testing.T) { + codec := NewTCodec() + param := new(txs.Tx) + + // Create new request object and unmarshal. + request := &rpc.RPCRequest{} + assert.NoError(t, json.Unmarshal(testBroadcastCallTxJsonRequest, request), + "Provided JSON test data does not unmarshal to rpc.RPCRequest object.") + assert.NoError(t, codec.DecodeBytesPtr(param, request.Params), + "RPC codec failed to decode params as transaction type.") + _, ok := (*param).(*txs.CallTx) + assert.True(t, ok, "Type byte 0x02 should unmarshal into CallTx.") +} diff --git a/rpc/v0/methods.go b/rpc/v0/methods.go index cc0a040aed6c92ecaf60fd8522f178457458ec3e..6a26848cc8f3a6cb38afe01b704a19d98f57c611 100644 --- a/rpc/v0/methods.go +++ b/rpc/v0/methods.go @@ -359,12 +359,13 @@ func (erisDbMethods *ErisDbMethods) CallCode(request *rpc.RPCRequest, requester } func (erisDbMethods *ErisDbMethods) BroadcastTx(request *rpc.RPCRequest, requester interface{}) (interface{}, int, error) { - param := &txs.CallTx{} - err := erisDbMethods.codec.DecodeBytes(param, request.Params) + // Accept all transaction types as parameter for broadcast. + param := new(txs.Tx) + err := erisDbMethods.codec.DecodeBytesPtr(param, request.Params) if err != nil { return nil, rpc.INVALID_PARAMS, err } - receipt, errC := erisDbMethods.pipe.Transactor().BroadcastTx(param) + receipt, errC := erisDbMethods.pipe.Transactor().BroadcastTx(*param) if errC != nil { return nil, rpc.INTERNAL_ERROR, errC } diff --git a/test/testdata/testdata/testdata.go b/rpc/v0/restServer_data_test.go similarity index 94% rename from test/testdata/testdata/testdata.go rename to rpc/v0/restServer_data_test.go index 2f212de66036c4ef868b75cb74a489602838998b..31fbaeb3b169dc78bbb76fe6700c4698843b2a4a 100644 --- a/test/testdata/testdata/testdata.go +++ b/rpc/v0/restServer_data_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package testdata +package rpc_v0 import ( account "github.com/eris-ltd/eris-db/account" @@ -20,7 +20,6 @@ import ( core_types "github.com/eris-ltd/eris-db/core/types" event "github.com/eris-ltd/eris-db/event" genesis "github.com/eris-ltd/eris-db/genesis" - rpc_v0 "github.com/eris-ltd/eris-db/rpc/v0" "github.com/eris-ltd/eris-db/rpc/v0/shared" transaction "github.com/eris-ltd/eris-db/txs" mintTypes "github.com/tendermint/tendermint/types" @@ -558,22 +557,22 @@ type ( } GetAccountData struct { - Input *rpc_v0.AddressParam `json:"input"` - Output *account.Account `json:"output"` + Input *AddressParam `json:"input"` + Output *account.Account `json:"output"` } GetAccountsData struct { - Input *rpc_v0.AccountsParam `json:"input"` + Input *AccountsParam `json:"input"` Output *core_types.AccountList `json:"output"` } GetStorageData struct { - Input *rpc_v0.AddressParam `json:"input"` - Output *core_types.Storage `json:"output"` + Input *AddressParam `json:"input"` + Output *core_types.Storage `json:"output"` } GetStorageAtData struct { - Input *rpc_v0.StorageAtParam `json:"input"` + Input *StorageAtParam `json:"input"` Output *core_types.StorageItem `json:"output"` } @@ -602,13 +601,13 @@ type ( } GetBlockData struct { - Input *rpc_v0.HeightParam `json:"input"` - Output *mintTypes.Block `json:"output"` + Input *HeightParam `json:"input"` + Output *mintTypes.Block `json:"output"` } GetBlocksData struct { - Input *rpc_v0.BlocksParam `json:"input"` - Output *core_types.Blocks `json:"output"` + Input *BlocksParam `json:"input"` + Output *core_types.Blocks `json:"output"` } GetConsensusStateData struct { @@ -644,18 +643,18 @@ type ( } GetPeerData struct { - Input *rpc_v0.PeerParam `json:"input"` + Input *PeerParam `json:"input"` Output *consensus_types.Peer `json:"output"` } TransactData struct { - Input *rpc_v0.TransactParam `json:"input"` - Output *transaction.Receipt `json:"output"` + Input *TransactParam `json:"input"` + Output *transaction.Receipt `json:"output"` } TransactCreateData struct { - Input *rpc_v0.TransactParam `json:"input"` - Output *transaction.Receipt `json:"output"` + Input *TransactParam `json:"input"` + Output *transaction.Receipt `json:"output"` } GetUnconfirmedTxsData struct { @@ -663,43 +662,43 @@ type ( } CallCodeData struct { - Input *rpc_v0.CallCodeParam `json:"input"` - Output *core_types.Call `json:"output"` + Input *CallCodeParam `json:"input"` + Output *core_types.Call `json:"output"` } CallData struct { - Input *rpc_v0.CallParam `json:"input"` - Output *core_types.Call `json:"output"` + Input *CallParam `json:"input"` + Output *core_types.Call `json:"output"` } EventSubscribeData struct { - Input *rpc_v0.EventIdParam `json:"input"` - Output *event.EventSub `json:"output"` + Input *EventIdParam `json:"input"` + Output *event.EventSub `json:"output"` } EventUnsubscribeData struct { - Input *rpc_v0.SubIdParam `json:"input"` - Output *event.EventUnsub `json:"output"` + Input *SubIdParam `json:"input"` + Output *event.EventUnsub `json:"output"` } TransactNameRegData struct { - Input *rpc_v0.TransactNameRegParam `json:"input"` - Output *transaction.Receipt `json:"output"` + Input *TransactNameRegParam `json:"input"` + Output *transaction.Receipt `json:"output"` } GetNameRegEntryData struct { - Input *rpc_v0.NameRegEntryParam `json:"input"` - Output *core_types.NameRegEntry `json:"output"` + Input *NameRegEntryParam `json:"input"` + Output *core_types.NameRegEntry `json:"output"` } GetNameRegEntriesData struct { - Input *rpc_v0.FilterListParam `json:"input"` + Input *FilterListParam `json:"input"` Output *core_types.ResultListNames `json:"output"` } /* EventPollData struct { - Input *rpc_v0.SubIdParam `json:"input"` + Input *SubIdParam `json:"input"` Output *event.PollResponse `json:"output"` } */ @@ -742,7 +741,7 @@ type ( ) func LoadTestData() *TestData { - codec := rpc_v0.NewTCodec() + codec := NewTCodec() testData := &TestData{} if err := codec.DecodeBytes(testData, []byte(testDataJson)); err != nil { panic(err) diff --git a/test/mock/pipe.go b/rpc/v0/restServer_pipe_test.go similarity index 92% rename from test/mock/pipe.go rename to rpc/v0/restServer_pipe_test.go index c3c1f33558a3f0139c32af2260755370c676cc80..6b084b9edb23b07c8976b912cbc25a426559caf6 100644 --- a/test/mock/pipe.go +++ b/rpc/v0/restServer_pipe_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package mock +package rpc_v0 import ( "fmt" @@ -25,7 +25,6 @@ import ( blockchain_types "github.com/eris-ltd/eris-db/blockchain/types" consensus_types "github.com/eris-ltd/eris-db/consensus/types" manager_types "github.com/eris-ltd/eris-db/manager/types" - td "github.com/eris-ltd/eris-db/test/testdata/testdata" "github.com/eris-ltd/eris-db/txs" "github.com/eris-ltd/eris-db/logging/loggers" @@ -37,7 +36,7 @@ import ( // Base struct. type MockPipe struct { - testData *td.TestData + testData *TestData accounts definitions.Accounts blockchain blockchain_types.Blockchain consensusEngine consensus_types.ConsensusEngine @@ -48,11 +47,11 @@ type MockPipe struct { } // Create a new mock tendermint pipe. -func NewMockPipe(td *td.TestData) definitions.Pipe { +func NewMockPipe(td *TestData) definitions.Pipe { return &MockPipe{ testData: td, accounts: &accounts{td}, - blockchain: &blockchain{td}, + blockchain: &mockBlockchain{td}, consensusEngine: &consensusEngine{td}, events: &eventer{td}, namereg: &namereg{td}, @@ -63,7 +62,7 @@ func NewMockPipe(td *td.TestData) definitions.Pipe { // Create a mock pipe with default mock data. func NewDefaultMockPipe() definitions.Pipe { - return NewMockPipe(td.LoadTestData()) + return NewMockPipe(LoadTestData()) } func (pipe *MockPipe) Accounts() definitions.Accounts { @@ -125,7 +124,7 @@ func (pipe *MockPipe) GenesisHash() []byte { // Accounts type accounts struct { - testData *td.TestData + testData *TestData } func (acc *accounts) GenPrivAccount() (*account.PrivAccount, error) { @@ -153,29 +152,29 @@ func (acc *accounts) StorageAt(address, key []byte) (*core_types.StorageItem, er } // Blockchain -type blockchain struct { - testData *td.TestData +type mockBlockchain struct { + testData *TestData } -func (this *blockchain) ChainId() string { +func (this *mockBlockchain) ChainId() string { return this.testData.GetChainId.Output.ChainId } -func (this *blockchain) Height() int { +func (this *mockBlockchain) Height() int { return this.testData.GetLatestBlockHeight.Output.Height } -func (this *blockchain) Block(height int) *mintTypes.Block { +func (this *mockBlockchain) Block(height int) *mintTypes.Block { return this.testData.GetBlock.Output } -func (this *blockchain) BlockMeta(height int) *mintTypes.BlockMeta { +func (this *mockBlockchain) BlockMeta(height int) *mintTypes.BlockMeta { return &mintTypes.BlockMeta{} } // Consensus type consensusEngine struct { - testData *td.TestData + testData *TestData } func (cons *consensusEngine) BroadcastTransaction(transaction []byte, @@ -239,7 +238,7 @@ func (cons *consensusEngine) PeerConsensusStates() map[string]string { // Events type eventer struct { - testData *td.TestData + testData *TestData } func (evntr *eventer) Subscribe(subId, event string, callback func(txs.EventData)) error { @@ -252,7 +251,7 @@ func (evntr *eventer) Unsubscribe(subId string) error { // NameReg type namereg struct { - testData *td.TestData + testData *TestData } func (nmreg *namereg) Entry(key string) (*core_types.NameRegEntry, error) { @@ -265,7 +264,7 @@ func (nmreg *namereg) Entries(filters []*event.FilterData) (*core_types.ResultLi // Txs type transactor struct { - testData *td.TestData + testData *TestData } func (trans *transactor) Call(fromAddress, toAddress, data []byte) (*core_types.Call, error) { diff --git a/test/mock/mock_web_api_test.go b/rpc/v0/restServer_test.go similarity index 97% rename from test/mock/mock_web_api_test.go rename to rpc/v0/restServer_test.go index decf5796d86e96cb9b9dae1f32faec6ed45d67fd..7cdf28039bd5fd11bd5d76201961710eb7867963 100644 --- a/test/mock/mock_web_api_test.go +++ b/rpc/v0/restServer_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package mock +package rpc_v0 // Basic imports import ( @@ -29,9 +29,7 @@ import ( core_types "github.com/eris-ltd/eris-db/core/types" event "github.com/eris-ltd/eris-db/event" rpc "github.com/eris-ltd/eris-db/rpc" - rpc_v0 "github.com/eris-ltd/eris-db/rpc/v0" server "github.com/eris-ltd/eris-db/server" - td "github.com/eris-ltd/eris-db/test/testdata/testdata" "github.com/eris-ltd/eris-db/txs" "github.com/eris-ltd/eris-db/rpc/v0/shared" @@ -55,18 +53,18 @@ type MockSuite struct { serveProcess *server.ServeProcess codec rpc.Codec sUrl string - testData *td.TestData + testData *TestData } func (mockSuite *MockSuite) SetupSuite() { gin.SetMode(gin.ReleaseMode) // Load the supporting objects. - testData := td.LoadTestData() + testData := LoadTestData() pipe := NewMockPipe(testData) - codec := &rpc_v0.TCodec{} + codec := &TCodec{} evtSubs := event.NewEventSubscriptions(pipe.Events()) // The server - restServer := rpc_v0.NewRestServer(codec, pipe, evtSubs) + restServer := NewRestServer(codec, pipe, evtSubs) sConf := server.DefaultServerConfig() sConf.Bind.Port = 31402 // Create a server process. @@ -76,7 +74,7 @@ func (mockSuite *MockSuite) SetupSuite() { panic(err) } mockSuite.serveProcess = proc - mockSuite.codec = rpc_v0.NewTCodec() + mockSuite.codec = NewTCodec() mockSuite.testData = testData mockSuite.sUrl = "http://localhost:31402" }