diff --git a/client/node_client.go b/client/node_client.go index c98ff55086e0dfb2fedab79e6916fce0b0dce167..3cac3db2a2d94b8a611144f6cfb9ec3863642070 100644 --- a/client/node_client.go +++ b/client/node_client.go @@ -21,9 +21,9 @@ import ( "github.com/hyperledger/burrow/crypto" "github.com/hyperledger/burrow/logging" "github.com/hyperledger/burrow/rpc" - tendermint_client "github.com/hyperledger/burrow/rpc/tm/client" + tmClient "github.com/hyperledger/burrow/rpc/tm/client" + rpcClient "github.com/hyperledger/burrow/rpc/tm/lib/client" "github.com/hyperledger/burrow/txs" - "github.com/tendermint/tendermint/rpc/lib/client" ) type NodeClient interface { @@ -75,8 +75,8 @@ func NewBurrowNodeClient(rpcString string, logger *logging.Logger) *burrowNodeCl // broadcast to blockchain node func (burrowNodeClient *burrowNodeClient) Broadcast(tx txs.Tx) (*txs.Receipt, error) { - client := rpcclient.NewURIClient(burrowNodeClient.broadcastRPC) - receipt, err := tendermint_client.BroadcastTx(client, tx) + client := rpcClient.NewURIClient(burrowNodeClient.broadcastRPC) + receipt, err := tmClient.BroadcastTx(client, tx) if err != nil { return nil, err } @@ -105,7 +105,7 @@ func (burrowNodeClient *burrowNodeClient) DeriveWebsocketClient() (nodeWsClient "websocket address", wsAddr, "endpoint", "/websocket", ) - wsClient := rpcclient.NewWSClient(wsAddr, "/websocket") + wsClient := rpcClient.NewWSClient(wsAddr, "/websocket") if err = wsClient.Start(); err != nil { return nil, err } @@ -124,8 +124,8 @@ func (burrowNodeClient *burrowNodeClient) DeriveWebsocketClient() (nodeWsClient func (burrowNodeClient *burrowNodeClient) Status() (GenesisHash []byte, ValidatorPublicKey []byte, LatestBlockHash []byte, LatestBlockHeight uint64, LatestBlockTime int64, err error) { - client := rpcclient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) - res, err := tendermint_client.Status(client) + client := rpcClient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) + res, err := tmClient.Status(client) if err != nil { err = fmt.Errorf("error connecting to node (%s) to get status: %s", burrowNodeClient.broadcastRPC, err.Error()) @@ -142,8 +142,8 @@ func (burrowNodeClient *burrowNodeClient) Status() (GenesisHash []byte, Validato } func (burrowNodeClient *burrowNodeClient) ChainId() (ChainName, ChainId string, GenesisHash []byte, err error) { - client := rpcclient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) - chainIdResult, err := tendermint_client.ChainId(client) + client := rpcClient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) + chainIdResult, err := tmClient.ChainId(client) if err != nil { err = fmt.Errorf("error connecting to node (%s) to get chain id: %s", burrowNodeClient.broadcastRPC, err.Error()) @@ -162,8 +162,8 @@ func (burrowNodeClient *burrowNodeClient) ChainId() (ChainName, ChainId string, func (burrowNodeClient *burrowNodeClient) QueryContract(callerAddress, calleeAddress crypto.Address, data []byte) (ret []byte, gasUsed uint64, err error) { - client := rpcclient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) - callResult, err := tendermint_client.Call(client, callerAddress, calleeAddress, data) + client := rpcClient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) + callResult, err := tmClient.Call(client, callerAddress, calleeAddress, data) if err != nil { err = fmt.Errorf("error (%v) connnecting to node (%s) to query contract at (%s) with data (%X)", err.Error(), burrowNodeClient.broadcastRPC, calleeAddress, data) @@ -176,10 +176,10 @@ func (burrowNodeClient *burrowNodeClient) QueryContract(callerAddress, calleeAdd func (burrowNodeClient *burrowNodeClient) QueryContractCode(address crypto.Address, code, data []byte) (ret []byte, gasUsed uint64, err error) { - client := rpcclient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) + client := rpcClient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) // TODO: [ben] Call and CallCode have an inconsistent signature; it makes sense for both to only // have a single address that is the contract to query. - callResult, err := tendermint_client.CallCode(client, address, code, data) + callResult, err := tmClient.CallCode(client, address, code, data) if err != nil { err = fmt.Errorf("error connnecting to node (%s) to query contract code at (%s) with data (%X) and code (%X): %v", burrowNodeClient.broadcastRPC, address, data, code, err.Error()) @@ -190,8 +190,8 @@ func (burrowNodeClient *burrowNodeClient) QueryContractCode(address crypto.Addre // GetAccount returns a copy of the account func (burrowNodeClient *burrowNodeClient) GetAccount(address crypto.Address) (acm.Account, error) { - client := rpcclient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) - account, err := tendermint_client.GetAccount(client, address) + client := rpcClient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) + account, err := tmClient.GetAccount(client, address) if err != nil { err = fmt.Errorf("error connecting to node (%s) to fetch account (%s): %s", burrowNodeClient.broadcastRPC, address, err.Error()) @@ -207,8 +207,8 @@ func (burrowNodeClient *burrowNodeClient) GetAccount(address crypto.Address) (ac // DumpStorage returns the full storage for an acm. func (burrowNodeClient *burrowNodeClient) DumpStorage(address crypto.Address) (*rpc.ResultDumpStorage, error) { - client := rpcclient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) - resultStorage, err := tendermint_client.DumpStorage(client, address) + client := rpcClient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) + resultStorage, err := tmClient.DumpStorage(client, address) if err != nil { return nil, fmt.Errorf("error connecting to node (%s) to get storage for account (%X): %s", burrowNodeClient.broadcastRPC, address, err.Error()) @@ -222,8 +222,8 @@ func (burrowNodeClient *burrowNodeClient) DumpStorage(address crypto.Address) (* func (burrowNodeClient *burrowNodeClient) GetName(name string) (owner crypto.Address, data string, expirationBlock uint64, err error) { - client := rpcclient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) - entryResult, err := tendermint_client.GetName(client, name) + client := rpcClient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) + entryResult, err := tmClient.GetName(client, name) if err != nil { err = fmt.Errorf("error connecting to node (%s) to get name registrar entry for name (%s)", burrowNodeClient.broadcastRPC, name) @@ -241,8 +241,8 @@ func (burrowNodeClient *burrowNodeClient) GetName(name string) (owner crypto.Add func (burrowNodeClient *burrowNodeClient) ListValidators() (blockHeight uint64, bondedValidators, unbondingValidators []acm.Validator, err error) { - client := rpcclient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) - validatorsResult, err := tendermint_client.ListValidators(client) + client := rpcClient.NewJSONRPCClient(burrowNodeClient.broadcastRPC) + validatorsResult, err := tmClient.ListValidators(client) if err != nil { err = fmt.Errorf("error connecting to node (%s) to get validators", burrowNodeClient.broadcastRPC) return diff --git a/client/websocket_client.go b/client/websocket_client.go index d4b9508a99592f187b1252cbf3b910b731e629e2..90e737b275f3a1ced1f731d60db4a28217f6b77b 100644 --- a/client/websocket_client.go +++ b/client/websocket_client.go @@ -22,14 +22,14 @@ import ( "encoding/json" "github.com/hyperledger/burrow/crypto" - exe_events "github.com/hyperledger/burrow/execution/events" + exeEvents "github.com/hyperledger/burrow/execution/events" "github.com/hyperledger/burrow/logging" "github.com/hyperledger/burrow/logging/structure" "github.com/hyperledger/burrow/rpc" - tm_client "github.com/hyperledger/burrow/rpc/tm/client" + "github.com/hyperledger/burrow/rpc/tm/client" + rpcClient "github.com/hyperledger/burrow/rpc/tm/lib/client" "github.com/hyperledger/burrow/txs" - "github.com/tendermint/tendermint/rpc/lib/client" - tm_types "github.com/tendermint/tendermint/types" + tmTypes "github.com/tendermint/tendermint/types" ) const ( @@ -38,7 +38,7 @@ const ( type Confirmation struct { BlockHash []byte - EventDataTx *exe_events.EventDataTx + EventDataTx *exeEvents.EventDataTx Exception error Error error } @@ -49,20 +49,20 @@ var _ NodeWebsocketClient = (*burrowNodeWebsocketClient)(nil) type burrowNodeWebsocketClient struct { // TODO: assert no memory leak on closing with open websocket - tendermintWebsocket *rpcclient.WSClient + tendermintWebsocket *rpcClient.WSClient logger *logging.Logger } // Subscribe to an eventid func (burrowNodeWebsocketClient *burrowNodeWebsocketClient) Subscribe(eventId string) error { // TODO we can in the background listen to the subscription id and remember it to ease unsubscribing later. - return tm_client.Subscribe(burrowNodeWebsocketClient.tendermintWebsocket, + return client.Subscribe(burrowNodeWebsocketClient.tendermintWebsocket, eventId) } // Unsubscribe from an eventid func (burrowNodeWebsocketClient *burrowNodeWebsocketClient) Unsubscribe(subscriptionId string) error { - return tm_client.Unsubscribe(burrowNodeWebsocketClient.tendermintWebsocket, + return client.Unsubscribe(burrowNodeWebsocketClient.tendermintWebsocket, subscriptionId) } @@ -75,11 +75,11 @@ func (burrowNodeWebsocketClient *burrowNodeWebsocketClient) WaitForConfirmation( confirmationChannel := make(chan Confirmation, 1) var latestBlockHash []byte - eventID := exe_events.EventStringAccountInput(inputAddr) + eventID := exeEvents.EventStringAccountInput(inputAddr) if err := burrowNodeWebsocketClient.Subscribe(eventID); err != nil { return nil, fmt.Errorf("Error subscribing to AccInput event (%s): %v", eventID, err) } - if err := burrowNodeWebsocketClient.Subscribe(tm_types.EventNewBlock); err != nil { + if err := burrowNodeWebsocketClient.Subscribe(tmTypes.EventNewBlock); err != nil { return nil, fmt.Errorf("Error subscribing to NewBlock event: %v", err) } // Read the incoming events @@ -112,7 +112,7 @@ func (burrowNodeWebsocketClient *burrowNodeWebsocketClient) WaitForConfirmation( } switch response.ID { - case tm_client.SubscribeRequestID: + case client.SubscribeRequestID: resultSubscribe := new(rpc.ResultSubscribe) err = json.Unmarshal(response.Result, resultSubscribe) if err != nil { @@ -125,7 +125,7 @@ func (burrowNodeWebsocketClient *burrowNodeWebsocketClient) WaitForConfirmation( "event", resultSubscribe.EventID, "subscription_id", resultSubscribe.SubscriptionID) - case tm_client.EventResponseID(tm_types.EventNewBlock): + case client.EventResponseID(tmTypes.EventNewBlock): resultEvent := new(rpc.ResultEvent) err = json.Unmarshal(response.Result, resultEvent) if err != nil { @@ -133,7 +133,7 @@ func (burrowNodeWebsocketClient *burrowNodeWebsocketClient) WaitForConfirmation( structure.ErrorKey, err) continue } - blockData := resultEvent.Tendermint.EventDataNewBlock + blockData := resultEvent.Tendermint.EventDataNewBlock() if blockData != nil { latestBlockHash = blockData.Block.Hash() burrowNodeWebsocketClient.logger.TraceMsg("Registered new block", @@ -142,7 +142,7 @@ func (burrowNodeWebsocketClient *burrowNodeWebsocketClient) WaitForConfirmation( ) } - case tm_client.EventResponseID(eventID): + case client.EventResponseID(eventID): resultEvent := new(rpc.ResultEvent) err = json.Unmarshal(response.Result, resultEvent) if err != nil { @@ -192,7 +192,7 @@ func (burrowNodeWebsocketClient *burrowNodeWebsocketClient) WaitForConfirmation( default: burrowNodeWebsocketClient.logger.InfoMsg("Received unsolicited response", "response_id", response.ID, - "expected_response_id", tm_client.EventResponseID(eventID)) + "expected_response_id", client.EventResponseID(eventID)) } } } diff --git a/core/integration/test_wrapper.go b/core/integration/test_wrapper.go index 751a52b99fd5b9e1fdbd62d73bf2f01c14f32962..79b5db460b908c8c5f8f387a5194efa95578cecd 100644 --- a/core/integration/test_wrapper.go +++ b/core/integration/test_wrapper.go @@ -48,7 +48,6 @@ const ( //var debugLogging = true var debugLogging = false - // We use this to wrap tests func TestWrapper(privateAccounts []acm.PrivateAccount, genesisDoc *genesis.GenesisDoc, runner func(*core.Kernel) int) int { fmt.Println("Running with integration TestWrapper (core/integration/test_wrapper.go)...") diff --git a/rpc/result.go b/rpc/result.go index aaa03f6f04ba6675a192eb1b7269ce08f6a28afe..63e05cf127b71705a87ff325c4efd19f6ff09f9f 100644 --- a/rpc/result.go +++ b/rpc/result.go @@ -21,15 +21,26 @@ import ( acm "github.com/hyperledger/burrow/account" "github.com/hyperledger/burrow/crypto" "github.com/hyperledger/burrow/execution" - exe_events "github.com/hyperledger/burrow/execution/events" - evm_events "github.com/hyperledger/burrow/execution/evm/events" + exeEvents "github.com/hyperledger/burrow/execution/events" + evmEvents "github.com/hyperledger/burrow/execution/evm/events" "github.com/hyperledger/burrow/genesis" "github.com/hyperledger/burrow/txs" - ctypes "github.com/tendermint/tendermint/consensus/types" + "github.com/tendermint/go-amino" + consensusTypes "github.com/tendermint/tendermint/consensus/types" "github.com/tendermint/tendermint/p2p" - tm_types "github.com/tendermint/tendermint/types" + "github.com/tendermint/tendermint/rpc/core/types" + tmTypes "github.com/tendermint/tendermint/types" ) +// When using Tendermint types like Block and Vote we are forced to wrap the outer object and use amino marshalling +var aminoCodec = amino.NewCodec() + +func init() { + //types.RegisterEvidences(AminoCodec) + //crypto.RegisterAmino(cdc) + core_types.RegisterAmino(aminoCodec) +} + type ResultGetStorage struct { Key []byte Value []byte @@ -64,12 +75,37 @@ type StorageItem struct { type ResultListBlocks struct { LastHeight uint64 - BlockMetas []*tm_types.BlockMeta + BlockMetas []*tmTypes.BlockMeta } type ResultGetBlock struct { - BlockMeta *tm_types.BlockMeta - Block *tm_types.Block + BlockMeta *BlockMeta + Block *Block +} + +type BlockMeta struct { + *tmTypes.BlockMeta +} + +func (bm BlockMeta) MarshalJSON() ([]byte, error) { + return aminoCodec.MarshalJSON(bm.BlockMeta) +} + +func (bm *BlockMeta) UnmarshalJSON(data []byte) (err error) { + return aminoCodec.UnmarshalJSON(data, &bm.BlockMeta) +} + +// Needed for go-amino handling of interface types +type Block struct { + *tmTypes.Block +} + +func (b Block) MarshalJSON() ([]byte, error) { + return aminoCodec.MarshalJSON(b.Block) +} + +func (b *Block) UnmarshalJSON(data []byte) (err error) { + return aminoCodec.UnmarshalJSON(data, &b.Block) } type ResultStatus struct { @@ -115,8 +151,8 @@ type ResultListValidators struct { } type ResultDumpConsensusState struct { - RoundState *ctypes.RoundState - PeerRoundStates []*ctypes.PeerRoundState + RoundState consensusTypes.RoundStateSimple + PeerRoundStates []*consensusTypes.PeerRoundState } type ResultPeers struct { @@ -155,8 +191,6 @@ type ResultBroadcastTx struct { txs.Receipt } -// Unwrap - func (rbt ResultBroadcastTx) MarshalJSON() ([]byte, error) { return json.Marshal(rbt.Receipt) } @@ -182,35 +216,32 @@ type ResultSignTx struct { Tx txs.Wrapper } -type ResultEventDataNewBlock struct { - tm_types.EventDataNewBlock `json:"unwrap"` +type TendermintEvent struct { + tmTypes.TMEventData } -type ResultTendermintEvent struct { - EventDataNewBlock *ResultEventDataNewBlock `json:",omitempty"` - EventDataNewBlockHeader *tm_types.EventDataNewBlockHeader `json:",omitempty"` - EventDataTx *tm_types.EventDataTx `json:",omitempty"` - EventDataRoundState *tm_types.EventDataRoundState `json:",omitempty"` - EventDataVote *tm_types.EventDataVote `json:",omitempty"` - EventDataProposalHeartbeat *tm_types.EventDataProposalHeartbeat `json:",omitempty"` - EventDataString *tm_types.EventDataString `json:",omitempty"` +func (te TendermintEvent) MarshalJSON() ([]byte, error) { + return aminoCodec.MarshalJSON(te.TMEventData) } -func (nb ResultEventDataNewBlock) MarshalJSON() ([]byte, error) { - return cdc.MarshalJSON(nb.EventDataNewBlock) +func (te *TendermintEvent) UnmarshalJSON(data []byte) (err error) { + return aminoCodec.UnmarshalJSON(data, &te.TMEventData) } -func (nb *ResultEventDataNewBlock) UnmarshalJSON(data []byte) (err error) { - return cdc.UnmarshalJSON(data, &nb.EventDataNewBlock) +func (te *TendermintEvent) EventDataNewBlock() *tmTypes.EventDataNewBlock { + if te != nil { + eventData, _ := te.TMEventData.(tmTypes.EventDataNewBlock) + return &eventData + } + return nil } type ResultEvent struct { - Event string - //TMEventData tm_types.TMEventData `json:",omitempty"` - Tendermint *ResultTendermintEvent `json:",omitempty"` - EventDataTx *exe_events.EventDataTx `json:",omitempty"` - EventDataCall *evm_events.EventDataCall `json:",omitempty"` - EventDataLog *evm_events.EventDataLog `json:",omitempty"` + Event string + Tendermint *TendermintEvent `json:",omitempty"` + EventDataTx *exeEvents.EventDataTx `json:",omitempty"` + EventDataCall *evmEvents.EventDataCall `json:",omitempty"` + EventDataLog *evmEvents.EventDataLog `json:",omitempty"` } // Map any supported event data element to our ResultEvent sum type @@ -219,34 +250,13 @@ func NewResultEvent(event string, eventData interface{}) (*ResultEvent, error) { Event: event, } switch ed := eventData.(type) { - case tm_types.TMEventData: - //res.TMEventData = ed - res.Tendermint = &ResultTendermintEvent{} - switch ted := ed.(type) { - case tm_types.EventDataNewBlock: - res.Tendermint.EventDataNewBlock = &ResultEventDataNewBlock{ted} - case tm_types.EventDataNewBlockHeader: - res.Tendermint.EventDataNewBlockHeader = &ted - case tm_types.EventDataTx: - res.Tendermint.EventDataTx = &ted - case tm_types.EventDataRoundState: - res.Tendermint.EventDataRoundState = &ted - case tm_types.EventDataVote: - res.Tendermint.EventDataVote = &ted - case tm_types.EventDataProposalHeartbeat: - res.Tendermint.EventDataProposalHeartbeat = &ted - case tm_types.EventDataString: - res.Tendermint.EventDataString = &ted - default: - return nil, fmt.Errorf("unsupported Tendermint event: %#v", ted) - } - case *exe_events.EventDataTx: + case tmTypes.TMEventData: + res.Tendermint = &TendermintEvent{ed} + case *exeEvents.EventDataTx: res.EventDataTx = ed - - case *evm_events.EventDataCall: + case *evmEvents.EventDataCall: res.EventDataCall = ed - - case *evm_events.EventDataLog: + case *evmEvents.EventDataLog: res.EventDataLog = ed default: return nil, fmt.Errorf("could not map event data of type %T to ResultEvent", eventData) diff --git a/rpc/result_test.go b/rpc/result_test.go index f8013feec4bddfca1c2e358fda100c320b6da43b..2aa750ba26cb4300a7a07d210d41c8074cc37d60 100644 --- a/rpc/result_test.go +++ b/rpc/result_test.go @@ -18,6 +18,8 @@ import ( "encoding/json" "testing" + goCrypto "github.com/tendermint/go-crypto" + acm "github.com/hyperledger/burrow/account" "github.com/hyperledger/burrow/crypto" "github.com/hyperledger/burrow/execution" @@ -25,7 +27,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tendermint/go-wire" - tm_types "github.com/tendermint/tendermint/types" + "github.com/tendermint/tendermint/consensus/types" + tmTypes "github.com/tendermint/tendermint/types" + "github.com/tendermint/tmlibs/common" ) func TestResultBroadcastTx(t *testing.T) { @@ -96,27 +100,73 @@ func TestResultCall_MarshalJSON(t *testing.T) { } func TestResultEvent(t *testing.T) { - eventDataNewBlock := tm_types.EventDataNewBlock{ - Block: &tm_types.Block{ - Header: &tm_types.Header{ + eventDataNewBlock := tmTypes.EventDataNewBlock{ + Block: &tmTypes.Block{ + Header: &tmTypes.Header{ ChainID: "chainy", NumTxs: 30, }, + LastCommit: &tmTypes.Commit{ + Precommits: []*tmTypes.Vote{ + { + Signature: goCrypto.SignatureEd25519{1, 2, 3}, + }, + }, + }, }, } res := ResultEvent{ - Tendermint: &ResultTendermintEvent{ - EventDataNewBlock: &eventDataNewBlock, + Tendermint: &TendermintEvent{ + TMEventData: &eventDataNewBlock, }, } bs, err := json.Marshal(res) require.NoError(t, err) resOut := new(ResultEvent) - json.Unmarshal(bs, resOut) + require.NoError(t, json.Unmarshal(bs, resOut)) bsOut, err := json.Marshal(resOut) require.NoError(t, err) assert.Equal(t, string(bs), string(bsOut)) //fmt.Println(string(bs)) //fmt.Println(string(bsOut)) } + +func TestResultGetBlock(t *testing.T) { + res := &ResultGetBlock{ + Block: &Block{&tmTypes.Block{ + LastCommit: &tmTypes.Commit{ + Precommits: []*tmTypes.Vote{ + { + Signature: goCrypto.SignatureEd25519{1, 2, 3}, + }, + }, + }, + }, + }, + } + bs, err := json.Marshal(res) + require.NoError(t, err) + resOut := new(ResultGetBlock) + require.NoError(t, json.Unmarshal([]byte(bs), resOut)) + bsOut, err := json.Marshal(resOut) + require.NoError(t, err) + assert.Equal(t, string(bs), string(bsOut)) +} + +func TestResultDumpConsensusState(t *testing.T) { + res := &ResultDumpConsensusState{ + RoundState: types.RoundStateSimple{ + HeightRoundStep: "34/0/3", + Votes: json.RawMessage(`[{"i'm a json": "32"}]`), + LockedBlockHash: common.HexBytes{'b', 'y', 't', 'e', 's'}, + }, + } + bs, err := json.Marshal(res) + require.NoError(t, err) + resOut := new(ResultDumpConsensusState) + require.NoError(t, json.Unmarshal([]byte(bs), resOut)) + bsOut, err := json.Marshal(resOut) + require.NoError(t, err) + assert.Equal(t, string(bs), string(bsOut)) +} diff --git a/rpc/service.go b/rpc/service.go index 415768f851caf0ca9d76252d6b344ddde20ec88c..f848bd60a3ba1c1ab97564065f96f0f92ad22c61 100644 --- a/rpc/service.go +++ b/rpc/service.go @@ -345,8 +345,8 @@ func (s *Service) ListNames(predicate func(*execution.NameRegEntry) bool) (*Resu func (s *Service) GetBlock(height uint64) (*ResultGetBlock, error) { return &ResultGetBlock{ - Block: s.nodeView.BlockStore().LoadBlock(int64(height)), - BlockMeta: s.nodeView.BlockStore().LoadBlockMeta(int64(height)), + Block: &Block{s.nodeView.BlockStore().LoadBlock(int64(height))}, + BlockMeta: &BlockMeta{s.nodeView.BlockStore().LoadBlockMeta(int64(height))}, }, nil } @@ -401,7 +401,7 @@ func (s *Service) DumpConsensusState() (*ResultDumpConsensusState, error) { return nil, err } return &ResultDumpConsensusState{ - RoundState: s.nodeView.RoundState(), + RoundState: s.nodeView.RoundState().RoundStateSimple(), PeerRoundStates: peerRoundState, }, nil } diff --git a/rpc/tm/client/websocket_client.go b/rpc/tm/client/websocket_client.go index 18d676a41df3ea50256a120d91b76f58d63fd3cc..96ba127f79c409da04cbf1b9f8062b9f46f8bdf7 100644 --- a/rpc/tm/client/websocket_client.go +++ b/rpc/tm/client/websocket_client.go @@ -18,11 +18,11 @@ import ( "context" "github.com/hyperledger/burrow/rpc/tm" - "github.com/tendermint/tendermint/rpc/lib/types" + "github.com/hyperledger/burrow/rpc/tm/lib/types" ) type WebsocketClient interface { - Send(ctx context.Context, request rpctypes.RPCRequest) error + Send(ctx context.Context, request types.RPCRequest) error } const SubscribeRequestID = "Subscribe" @@ -33,7 +33,7 @@ func EventResponseID(eventID string) string { } func Subscribe(wsc WebsocketClient, eventID string) error { - req, err := rpctypes.MapToRequest(tm.AminoCodec, SubscribeRequestID, + req, err := types.MapToRequest(SubscribeRequestID, "subscribe", map[string]interface{}{"eventID": eventID}) if err != nil { return err @@ -42,7 +42,7 @@ func Subscribe(wsc WebsocketClient, eventID string) error { } func Unsubscribe(websocketClient WebsocketClient, subscriptionID string) error { - req, err := rpctypes.MapToRequest(tm.AminoCodec, UnsubscribeRequestID, + req, err := types.MapToRequest(UnsubscribeRequestID, "unsubscribe", map[string]interface{}{"subscriptionID": subscriptionID}) if err != nil { return err diff --git a/rpc/tm/integration/client_test.go b/rpc/tm/integration/client_test.go index da04bb2adc39606f3a5682de4fb012b62df921dd..87bb496acb1ef048f62e027b6c91a84b915f5570 100644 --- a/rpc/tm/integration/client_test.go +++ b/rpc/tm/integration/client_test.go @@ -22,6 +22,9 @@ import ( "testing" "time" + "fmt" + "strings" + "github.com/hyperledger/burrow/binary" exe_events "github.com/hyperledger/burrow/execution/events" "github.com/hyperledger/burrow/rpc" @@ -386,11 +389,8 @@ func TestDumpConsensusState(t *testing.T) { waitNBlocks(t, wsc, 3) resp, err := tm_client.DumpConsensusState(client) assert.NoError(t, err) - commitTime := resp.RoundState.CommitTime assert.NotZero(t, startTime) - assert.NotZero(t, commitTime) - assert.True(t, commitTime.Unix() > startTime.Unix(), - "Commit time %v should be later than start time %v", commitTime, startTime) - assert.Equal(t, types.RoundStepNewHeight, resp.RoundState.Step) + assert.Equal(t, fmt.Sprintf("/0/%d", types.RoundStepNewHeight), + strings.TrimLeft(resp.RoundState.HeightRoundStep, "0123456789")) }) } diff --git a/rpc/tm/integration/shared.go b/rpc/tm/integration/shared.go index 18cc0249ab2e1a2704fd2e67bbef56565d21f0e3..e7b58d95de50d11d16efa2af153723e81c297268 100644 --- a/rpc/tm/integration/shared.go +++ b/rpc/tm/integration/shared.go @@ -28,11 +28,10 @@ import ( "github.com/hyperledger/burrow/crypto" "github.com/hyperledger/burrow/execution" "github.com/hyperledger/burrow/rpc" - "github.com/hyperledger/burrow/rpc/tm" - tm_client "github.com/hyperledger/burrow/rpc/tm/client" + tmClient "github.com/hyperledger/burrow/rpc/tm/client" + rpcClient "github.com/hyperledger/burrow/rpc/tm/lib/client" "github.com/hyperledger/burrow/txs" "github.com/stretchr/testify/require" - "github.com/tendermint/tendermint/rpc/lib/client" ) const ( @@ -44,24 +43,19 @@ const ( // global variables for use across all tests var ( privateAccounts = integration.MakePrivateAccounts(5) // make keys - jsonRpcClient = rpcclient.NewJSONRPCClient(rpcAddr) - httpClient = rpcclient.NewURIClient(rpcAddr) - clients = map[string]tm_client.RPCClient{ + jsonRpcClient = rpcClient.NewJSONRPCClient(rpcAddr) + httpClient = rpcClient.NewURIClient(rpcAddr) + clients = map[string]tmClient.RPCClient{ "JSONRPC": jsonRpcClient, "HTTP": httpClient, } genesisDoc = integration.TestGenesisDoc(privateAccounts) ) -func init() { - jsonRpcClient.SetCodec(tm.AminoCodec) - httpClient.SetCodec(tm.AminoCodec) -} - //------------------------------------------------------------------------------- // some default transaction functions -func makeDefaultSendTx(t *testing.T, client tm_client.RPCClient, addr crypto.Address, amt uint64) *txs.SendTx { +func makeDefaultSendTx(t *testing.T, client tmClient.RPCClient, addr crypto.Address, amt uint64) *txs.SendTx { sequence := getSequence(t, client, privateAccounts[0].Address()) tx := txs.NewSendTx() tx.AddInputWithSequence(privateAccounts[0].PublicKey(), amt, sequence+1) @@ -69,13 +63,13 @@ func makeDefaultSendTx(t *testing.T, client tm_client.RPCClient, addr crypto.Add return tx } -func makeDefaultSendTxSigned(t *testing.T, client tm_client.RPCClient, addr crypto.Address, amt uint64) *txs.SendTx { +func makeDefaultSendTxSigned(t *testing.T, client tmClient.RPCClient, addr crypto.Address, amt uint64) *txs.SendTx { tx := makeDefaultSendTx(t, client, addr, amt) require.NoError(t, tx.Sign(genesisDoc.ChainID(), privateAccounts[0])) return tx } -func makeDefaultCallTx(t *testing.T, client tm_client.RPCClient, addr *crypto.Address, code []byte, amt, gasLim, +func makeDefaultCallTx(t *testing.T, client tmClient.RPCClient, addr *crypto.Address, code []byte, amt, gasLim, fee uint64) *txs.CallTx { sequence := getSequence(t, client, privateAccounts[0].Address()) tx := txs.NewCallTxWithSequence(privateAccounts[0].PublicKey(), addr, code, amt, gasLim, fee, @@ -84,7 +78,7 @@ func makeDefaultCallTx(t *testing.T, client tm_client.RPCClient, addr *crypto.Ad return tx } -func makeDefaultNameTx(t *testing.T, client tm_client.RPCClient, name, value string, amt, fee uint64) *txs.NameTx { +func makeDefaultNameTx(t *testing.T, client tmClient.RPCClient, name, value string, amt, fee uint64) *txs.NameTx { sequence := getSequence(t, client, privateAccounts[0].Address()) tx := txs.NewNameTxWithSequence(privateAccounts[0].PublicKey(), name, value, amt, fee, sequence+1) require.NoError(t, tx.Sign(genesisDoc.ChainID(), privateAccounts[0])) @@ -95,8 +89,8 @@ func makeDefaultNameTx(t *testing.T, client tm_client.RPCClient, name, value str // rpc call wrappers (fail on err) // get an account's sequence number -func getSequence(t *testing.T, client tm_client.RPCClient, addr crypto.Address) uint64 { - acc, err := tm_client.GetAccount(client, addr) +func getSequence(t *testing.T, client tmClient.RPCClient, addr crypto.Address) uint64 { + acc, err := tmClient.GetAccount(client, addr) if err != nil { t.Fatal(err) } @@ -107,8 +101,8 @@ func getSequence(t *testing.T, client tm_client.RPCClient, addr crypto.Address) } // get the account -func getAccount(t *testing.T, client tm_client.RPCClient, addr crypto.Address) acm.Account { - ac, err := tm_client.GetAccount(client, addr) +func getAccount(t *testing.T, client tmClient.RPCClient, addr crypto.Address) acm.Account { + ac, err := tmClient.GetAccount(client, addr) if err != nil { t.Fatal(err) } @@ -116,9 +110,9 @@ func getAccount(t *testing.T, client tm_client.RPCClient, addr crypto.Address) a } // sign transaction -func signTx(t *testing.T, client tm_client.RPCClient, tx txs.Tx, +func signTx(t *testing.T, client tmClient.RPCClient, tx txs.Tx, privAcc *acm.ConcretePrivateAccount) txs.Tx { - signedTx, err := tm_client.SignTx(client, tx, []*acm.ConcretePrivateAccount{privAcc}) + signedTx, err := tmClient.SignTx(client, tx, []*acm.ConcretePrivateAccount{privAcc}) if err != nil { t.Fatal(err) } @@ -126,8 +120,8 @@ func signTx(t *testing.T, client tm_client.RPCClient, tx txs.Tx, } // broadcast transaction -func broadcastTx(t *testing.T, client tm_client.RPCClient, tx txs.Tx) *txs.Receipt { - rec, err := tm_client.BroadcastTx(client, tx) +func broadcastTx(t *testing.T, client tmClient.RPCClient, tx txs.Tx) *txs.Receipt { + rec, err := tmClient.BroadcastTx(client, tx) require.NoError(t, err) return rec } @@ -135,24 +129,24 @@ func broadcastTx(t *testing.T, client tm_client.RPCClient, tx txs.Tx) *txs.Recei // dump all storage for an account. currently unused func dumpStorage(t *testing.T, addr crypto.Address) *rpc.ResultDumpStorage { client := clients["HTTP"] - resp, err := tm_client.DumpStorage(client, addr) + resp, err := tmClient.DumpStorage(client, addr) if err != nil { t.Fatal(err) } return resp } -func getStorage(t *testing.T, client tm_client.RPCClient, addr crypto.Address, key []byte) []byte { - resp, err := tm_client.GetStorage(client, addr, key) +func getStorage(t *testing.T, client tmClient.RPCClient, addr crypto.Address, key []byte) []byte { + resp, err := tmClient.GetStorage(client, addr, key) if err != nil { t.Fatal(err) } return resp } -func callCode(t *testing.T, client tm_client.RPCClient, fromAddress crypto.Address, code, data, +func callCode(t *testing.T, client tmClient.RPCClient, fromAddress crypto.Address, code, data, expected []byte) { - resp, err := tm_client.CallCode(client, fromAddress, code, data) + resp, err := tmClient.CallCode(client, fromAddress, code, data) if err != nil { t.Fatal(err) } @@ -163,9 +157,9 @@ func callCode(t *testing.T, client tm_client.RPCClient, fromAddress crypto.Addre } } -func callContract(t *testing.T, client tm_client.RPCClient, fromAddress, toAddress crypto.Address, +func callContract(t *testing.T, client tmClient.RPCClient, fromAddress, toAddress crypto.Address, data, expected []byte) { - resp, err := tm_client.Call(client, fromAddress, toAddress, data) + resp, err := tmClient.Call(client, fromAddress, toAddress, data) if err != nil { t.Fatal(err) } @@ -177,8 +171,8 @@ func callContract(t *testing.T, client tm_client.RPCClient, fromAddress, toAddre } // get the namereg entry -func getNameRegEntry(t *testing.T, client tm_client.RPCClient, name string) *execution.NameRegEntry { - entry, err := tm_client.GetName(client, name) +func getNameRegEntry(t *testing.T, client tmClient.RPCClient, name string) *execution.NameRegEntry { + entry, err := tmClient.GetName(client, name) if err != nil { t.Fatal(err) } diff --git a/rpc/tm/integration/websocket_client_test.go b/rpc/tm/integration/websocket_client_test.go index 4f06a5915bb5bdd52f5320fa8f8cbd85870de15d..9ff32410da0f6a27a433147c6044ba59fd4248bd 100644 --- a/rpc/tm/integration/websocket_client_test.go +++ b/rpc/tm/integration/websocket_client_test.go @@ -54,7 +54,7 @@ func TestWSNewBlock(t *testing.T) { }() waitForEvent(t, wsc, eid, func() {}, func(eventID string, resultEvent *rpc.ResultEvent) (bool, error) { - fmt.Println("Check: ", resultEvent.Tendermint.EventDataNewBlock.Block) + fmt.Println("Check: ", resultEvent.Tendermint.EventDataNewBlock().Block) return true, nil }) } @@ -76,7 +76,7 @@ func TestWSBlockchainGrowth(t *testing.T) { for i := int64(0); i < 2; i++ { waitForEvent(t, wsc, eid, func() {}, func(eventID string, resultEvent *rpc.ResultEvent) (bool, error) { - eventDataNewBlock := resultEvent.Tendermint.EventDataNewBlock + eventDataNewBlock := resultEvent.Tendermint.EventDataNewBlock() if eventDataNewBlock == nil { t.Fatalf("Was expecting EventDataNewBlock but got %v", resultEvent) } @@ -318,7 +318,7 @@ Subscribe: if response.ID == tm_client.EventResponseID(tm_types.EventNewBlock) { res := new(rpc.ResultEvent) json.Unmarshal(response.Result, res) - enb := res.Tendermint.EventDataNewBlock + enb := res.Tendermint.EventDataNewBlock() if enb != nil { assert.Equal(t, genesisDoc.ChainID(), enb.Block.ChainID) if blocksSeen > 1 { diff --git a/rpc/tm/integration/websocket_helpers.go b/rpc/tm/integration/websocket_helpers.go index 9052eac9261d1288a4e9f8cb928daa9988c0d104..4397010b8158ef5aa470026bd94478f06649e57e 100644 --- a/rpc/tm/integration/websocket_helpers.go +++ b/rpc/tm/integration/websocket_helpers.go @@ -28,12 +28,12 @@ import ( "github.com/hyperledger/burrow/crypto" "github.com/hyperledger/burrow/execution/events" "github.com/hyperledger/burrow/rpc" - tm_client "github.com/hyperledger/burrow/rpc/tm/client" + tmClient "github.com/hyperledger/burrow/rpc/tm/client" + rpcClient "github.com/hyperledger/burrow/rpc/tm/lib/client" + rpcTypes "github.com/hyperledger/burrow/rpc/tm/lib/types" "github.com/hyperledger/burrow/txs" "github.com/stretchr/testify/require" - "github.com/tendermint/tendermint/rpc/lib/client" - "github.com/tendermint/tendermint/rpc/lib/types" - tm_types "github.com/tendermint/tendermint/types" + tmTypes "github.com/tendermint/tendermint/types" ) const ( @@ -43,31 +43,31 @@ const ( //-------------------------------------------------------------------------------- // Utilities for testing the websocket service -type blockPredicate func(block *tm_types.Block) bool +type blockPredicate func(block *tmTypes.Block) bool type resultEventChecker func(eventID string, resultEvent *rpc.ResultEvent) (bool, error) // create a new connection -func newWSClient() *rpcclient.WSClient { - wsc := rpcclient.NewWSClient(websocketAddr, websocketEndpoint) +func newWSClient() *rpcClient.WSClient { + wsc := rpcClient.NewWSClient(websocketAddr, websocketEndpoint) if err := wsc.Start(); err != nil { panic(err) } return wsc } -func stopWSClient(wsc *rpcclient.WSClient) { +func stopWSClient(wsc *rpcClient.WSClient) { wsc.Stop() } // subscribe to an event -func subscribe(t *testing.T, wsc *rpcclient.WSClient, eventId string) { - if err := tm_client.Subscribe(wsc, eventId); err != nil { +func subscribe(t *testing.T, wsc *rpcClient.WSClient, eventId string) { + if err := tmClient.Subscribe(wsc, eventId); err != nil { t.Fatal(err) } } -func subscribeAndGetSubscriptionId(t *testing.T, wsc *rpcclient.WSClient, eventId string) string { - if err := tm_client.Subscribe(wsc, eventId); err != nil { +func subscribeAndGetSubscriptionId(t *testing.T, wsc *rpcClient.WSClient, eventId string) string { + if err := tmClient.Subscribe(wsc, eventId); err != nil { t.Fatal(err) } @@ -78,7 +78,7 @@ func subscribeAndGetSubscriptionId(t *testing.T, wsc *rpcclient.WSClient, eventI t.Fatal("Timeout waiting for subscription result") case response := <-wsc.ResponsesCh: require.Nil(t, response.Error, "Got error response from websocket channel: %v", response.Error) - if response.ID == tm_client.SubscribeRequestID { + if response.ID == tmClient.SubscribeRequestID { res := new(rpc.ResultSubscribe) err := json.Unmarshal(response.Result, res) if err == nil { @@ -90,14 +90,14 @@ func subscribeAndGetSubscriptionId(t *testing.T, wsc *rpcclient.WSClient, eventI } // unsubscribe from an event -func unsubscribe(t *testing.T, wsc *rpcclient.WSClient, subscriptionId string) { - if err := tm_client.Unsubscribe(wsc, subscriptionId); err != nil { +func unsubscribe(t *testing.T, wsc *rpcClient.WSClient, subscriptionId string) { + if err := tmClient.Unsubscribe(wsc, subscriptionId); err != nil { t.Fatal(err) } } // broadcast transaction and wait for new block -func broadcastTxAndWait(t *testing.T, client tm_client.RPCClient, tx txs.Tx) (*txs.Receipt, error) { +func broadcastTxAndWait(t *testing.T, client tmClient.RPCClient, tx txs.Tx) (*txs.Receipt, error) { wsc := newWSClient() defer stopWSClient(wsc) inputs := tx.GetInputs() @@ -111,7 +111,7 @@ func broadcastTxAndWait(t *testing.T, client tm_client.RPCClient, tx txs.Tx) (*t err = subscribeAndWaitForNext(t, wsc, events.EventStringAccountInput(address), func() { - rec, err = tm_client.BroadcastTx(client, tx) + rec, err = tmClient.BroadcastTx(client, tx) }, func(eventID string, resultEvent *rpc.ResultEvent) (bool, error) { return true, nil }) @@ -123,7 +123,7 @@ func broadcastTxAndWait(t *testing.T, client tm_client.RPCClient, tx txs.Tx) (*t func nextBlockPredicateFn() blockPredicate { initialHeight := int64(-1) - return func(block *tm_types.Block) bool { + return func(block *tmTypes.Block) bool { if initialHeight <= 0 { initialHeight = block.Height return false @@ -138,28 +138,28 @@ func nextBlockPredicateFn() blockPredicate { } } -func waitNBlocks(t *testing.T, wsc *rpcclient.WSClient, n int) { +func waitNBlocks(t *testing.T, wsc *rpcClient.WSClient, n int) { i := 0 require.NoError(t, runThenWaitForBlock(t, wsc, - func(block *tm_types.Block) bool { + func(block *tmTypes.Block) bool { i++ return i >= n }, func() {})) } -func runThenWaitForBlock(t *testing.T, wsc *rpcclient.WSClient, predicate blockPredicate, runner func()) error { +func runThenWaitForBlock(t *testing.T, wsc *rpcClient.WSClient, predicate blockPredicate, runner func()) error { eventDataChecker := func(event string, eventData *rpc.ResultEvent) (bool, error) { - eventDataNewBlock := eventData.Tendermint.EventDataNewBlock + eventDataNewBlock := eventData.Tendermint.EventDataNewBlock() if eventDataNewBlock == nil { return false, fmt.Errorf("could not convert %#v to EventDataNewBlock", eventData) } return predicate(eventDataNewBlock.Block), nil } - return subscribeAndWaitForNext(t, wsc, tm_types.EventNewBlock, runner, eventDataChecker) + return subscribeAndWaitForNext(t, wsc, tmTypes.EventNewBlock, runner, eventDataChecker) } -func subscribeAndWaitForNext(t *testing.T, wsc *rpcclient.WSClient, event string, runner func(), +func subscribeAndWaitForNext(t *testing.T, wsc *rpcClient.WSClient, event string, runner func(), checker resultEventChecker) error { subId := subscribeAndGetSubscriptionId(t, wsc, event) @@ -174,7 +174,7 @@ func subscribeAndWaitForNext(t *testing.T, wsc *rpcclient.WSClient, event string // stopWaiting is true waitForEvent will return or if stopWaiting is false // waitForEvent will keep listening for new events. If an error is returned // waitForEvent will fail the test. -func waitForEvent(t *testing.T, wsc *rpcclient.WSClient, eventID string, runner func(), +func waitForEvent(t *testing.T, wsc *rpcClient.WSClient, eventID string, runner func(), checker resultEventChecker) error { // go routine to wait for websocket msg @@ -196,7 +196,7 @@ func waitForEvent(t *testing.T, wsc *rpcclient.WSClient, eventID string, runner errCh <- r.Error return } - if r.ID == tm_client.EventResponseID(eventID) { + if r.ID == tmClient.EventResponseID(eventID) { resultEvent, err := readResponse(r) if err != nil { errCh <- err @@ -234,13 +234,11 @@ func waitForEvent(t *testing.T, wsc *rpcclient.WSClient, eventID string, runner return nil } -func readResponse(r rpctypes.RPCResponse) (*rpc.ResultEvent, error) { +func readResponse(r rpcTypes.RPCResponse) (*rpc.ResultEvent, error) { if r.Error != nil { return nil, r.Error } resultEvent := new(rpc.ResultEvent) - //fmt.Println(string(r.Result)) - //err := tm.AminoCodec.UnmarshalJSON(r.Result, resultEvent) err := json.Unmarshal(r.Result, resultEvent) if err != nil { return nil, err diff --git a/rpc/tm/lib/doc.go b/rpc/tm/lib/doc.go deleted file mode 100644 index 2bc438593705184b5ba2a94e602a350ab69fe1cc..0000000000000000000000000000000000000000 --- a/rpc/tm/lib/doc.go +++ /dev/null @@ -1,103 +0,0 @@ -/* -HTTP RPC server supporting calls via uri params, jsonrpc, and jsonrpc over websockets - -# Client Requests - -Suppose we want to expose the rpc function `HelloWorld(name string, num int)`. - -## GET (URI) - -As a GET request, it would have URI encoded parameters, and look like: - -``` -curl 'http://localhost:8008/hello_world?name="my_world"&num=5' -``` - -Note the `'` around the url, which is just so bash doesn't ignore the quotes in `"my_world"`. -This should also work: - -``` -curl http://localhost:8008/hello_world?name=\"my_world\"&num=5 -``` - -A GET request to `/` returns a list of available endpoints. -For those which take arguments, the arguments will be listed in order, with `_` where the actual value should be. - -## POST (JSONRPC) - -As a POST request, we use JSONRPC. For instance, the same request would have this as the body: - -``` -{ - "jsonrpc": "2.0", - "id": "anything", - "method": "hello_world", - "params": { - "name": "my_world", - "num": 5 - } -} -``` - -With the above saved in file `data.json`, we can make the request with - -``` -curl --data @data.json http://localhost:8008 -``` - -## WebSocket (JSONRPC) - -All requests are exposed over websocket in the same form as the POST JSONRPC. -Websocket connections are available at their own endpoint, typically `/websocket`, -though this is configurable when starting the server. - -# Server Definition - -Define some types and routes: - -``` -type ResultStatus struct { - Value string -} - -// Define some routes -var Routes = map[string]*rpcserver.RPCFunc{ - "status": rpcserver.NewRPCFunc(Status, "arg"), -} - -// an rpc function -func Status(v string) (*ResultStatus, error) { - return &ResultStatus{v}, nil -} - -``` - -Now start the server: - -``` -mux := http.NewServeMux() -rpcserver.RegisterRPCFuncs(mux, Routes) -wm := rpcserver.NewWebsocketManager(Routes) -mux.HandleFunc("/websocket", wm.WebsocketHandler) -logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) -go func() { - _, err := rpcserver.StartHTTPServer("0.0.0.0:8008", mux, logger) - if err != nil { - panic(err) - } -}() - -``` - -Note that unix sockets are supported as well (eg. `/path/to/socket` instead of `0.0.0.0:8008`) - -Now see all available endpoints by sending a GET request to `0.0.0.0:8008`. -Each route is available as a GET request, as a JSONRPCv2 POST request, and via JSONRPCv2 over websockets. - - -# Examples - -* [Tendermint](https://github.com/tendermint/tendermint/blob/master/rpc/core/routes.go) -* [tm-monitor](https://github.com/tendermint/tools/blob/master/tm-monitor/rpc.go) -*/ -package rpc diff --git a/rpc/tm/lib/lib.go b/rpc/tm/lib/lib.go new file mode 100644 index 0000000000000000000000000000000000000000..31b495a83b77ccc0477ef1b9862bb7f0a527b40e --- /dev/null +++ b/rpc/tm/lib/lib.go @@ -0,0 +1,4 @@ +// Originally copied from tendermint/rpc/lib and stripped of go-amino serialisation library in favour go +// stdlib json module + +package lib diff --git a/rpc/tm/lib/rpc_test.go b/rpc/tm/lib/rpc_test.go index f34b09f68f1c10e011565934847f796daf6920ff..0a21c0d83db84d8d504c783a4a593d65ea2f50e8 100644 --- a/rpc/tm/lib/rpc_test.go +++ b/rpc/tm/lib/rpc_test.go @@ -1,4 +1,4 @@ -package rpc +package lib import ( "bytes" @@ -14,16 +14,14 @@ import ( "time" "github.com/go-kit/kit/log/term" + "github.com/hyperledger/burrow/logging/lifecycle" + "github.com/hyperledger/burrow/rpc/tm/lib/client" + "github.com/hyperledger/burrow/rpc/tm/lib/server" + "github.com/hyperledger/burrow/rpc/tm/lib/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - - "github.com/tendermint/go-amino" cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" - - client "github.com/tendermint/tendermint/rpc/lib/client" - server "github.com/tendermint/tendermint/rpc/lib/server" - types "github.com/tendermint/tendermint/rpc/lib/types" ) // Client and Server should work over tcp or unix sockets @@ -61,9 +59,6 @@ var Routes = map[string]*server.RPCFunc{ "echo_int": server.NewRPCFunc(EchoIntResult, "arg"), } -// Amino codec required to encode/decode everything above. -var RoutesCdc = amino.NewCodec() - func EchoResult(v string) (*ResultEcho, error) { return &ResultEcho{v}, nil } @@ -105,7 +100,7 @@ var colorFn = func(keyvals ...interface{}) term.FgBgColor { // launch unix and tcp servers func setup() { - logger := log.NewTMLoggerWithColorFn(log.NewSyncWriter(os.Stdout), colorFn) + logger, _ := lifecycle.NewStdErrLogger() cmd := exec.Command("rm", "-f", unixSocket) err := cmd.Start() @@ -118,9 +113,8 @@ func setup() { tcpLogger := logger.With("socket", "tcp") mux := http.NewServeMux() - server.RegisterRPCFuncs(mux, Routes, RoutesCdc, tcpLogger) - wm := server.NewWebsocketManager(Routes, RoutesCdc, server.ReadWait(5*time.Second), server.PingPeriod(1*time.Second)) - wm.SetLogger(tcpLogger) + server.RegisterRPCFuncs(mux, Routes, tcpLogger) + wm := server.NewWebsocketManager(Routes, logger, server.ReadWait(5*time.Second), server.PingPeriod(1*time.Second)) mux.HandleFunc(websocketEndpoint, wm.WebsocketHandler) go func() { _, err := server.StartHTTPServer(tcpAddr, mux, tcpLogger) @@ -131,9 +125,8 @@ func setup() { unixLogger := logger.With("socket", "unix") mux2 := http.NewServeMux() - server.RegisterRPCFuncs(mux2, Routes, RoutesCdc, unixLogger) - wm = server.NewWebsocketManager(Routes, RoutesCdc) - wm.SetLogger(unixLogger) + server.RegisterRPCFuncs(mux2, Routes, unixLogger) + wm = server.NewWebsocketManager(Routes, logger) mux2.HandleFunc(websocketEndpoint, wm.WebsocketHandler) go func() { _, err := server.StartHTTPServer(unixAddr, mux2, unixLogger) diff --git a/rpc/tm/lib/server/http_server.go b/rpc/tm/lib/server/http_server.go index d16696d48b85bb3b06e3f570feb26bd251142b46..dfb350f9c553a83fb31f79437835bdfc7ab21002 100644 --- a/rpc/tm/lib/server/http_server.go +++ b/rpc/tm/lib/server/http_server.go @@ -41,46 +41,6 @@ func StartHTTPServer(listenAddr string, handler http.Handler, logger *logging.Lo return listener, nil } -func StartHTTPAndTLSServer(listenAddr string, handler http.Handler, certFile, keyFile string, - logger *logging.Logger) (listener net.Listener, err error) { - - var proto, addr string - parts := strings.SplitN(listenAddr, "://", 2) - if len(parts) != 2 { - return nil, errors.Errorf("Invalid listening address %s (use fully formed addresses, including the tcp:// or unix:// prefix)", listenAddr) - } - proto, addr = parts[0], parts[1] - - logger.InfoMsg("Starting RPC HTTPS server", "listen_address", listenAddr, "cert_file", certFile, - "key_file", keyFile) - listener, err = net.Listen(proto, addr) - if err != nil { - return nil, errors.Errorf("Failed to listen on %v: %v", listenAddr, err) - } - - go func() { - err := http.ServeTLS( - listener, - RecoverAndLogHandler(handler, logger), - certFile, - keyFile, - ) - logger.TraceMsg("RPC HTTPS server stopped", structure.ErrorKey, err) - }() - return listener, nil -} - -func WriteRPCResponseHTTPError(w http.ResponseWriter, httpCode int, res types.RPCResponse) { - jsonBytes, err := json.MarshalIndent(res, "", " ") - if err != nil { - panic(err) - } - - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(httpCode) - w.Write(jsonBytes) // nolint: errcheck, gas -} - func WriteRPCResponseHTTP(w http.ResponseWriter, res types.RPCResponse) { jsonBytes, err := json.MarshalIndent(res, "", " ") if err != nil { diff --git a/rpc/tm/methods.go b/rpc/tm/methods.go index 057241c1d333b09449b7fa2f350949ecd3a69bc7..987d4893ac5426d49a6f6c185692fd1fdb8a60b0 100644 --- a/rpc/tm/methods.go +++ b/rpc/tm/methods.go @@ -11,9 +11,9 @@ import ( "github.com/hyperledger/burrow/execution" "github.com/hyperledger/burrow/logging" "github.com/hyperledger/burrow/rpc" + "github.com/hyperledger/burrow/rpc/tm/lib/server" + "github.com/hyperledger/burrow/rpc/tm/lib/types" "github.com/hyperledger/burrow/txs" - gorpc "github.com/tendermint/tendermint/rpc/lib/server" - "github.com/tendermint/tendermint/rpc/lib/types" ) // Method names @@ -57,13 +57,13 @@ const ( SignTx = "unsafe/sign_tx" ) -const SubscriptionTimeoutSeconds = 5 * time.Second +const SubscriptionTimeout = 5 * time.Second -func GetRoutes(service *rpc.Service, logger *logging.Logger) map[string]*gorpc.RPCFunc { +func GetRoutes(service *rpc.Service, logger *logging.Logger) map[string]*server.RPCFunc { logger = logger.WithScope("GetRoutes") - return map[string]*gorpc.RPCFunc{ + return map[string]*server.RPCFunc{ // Transact - BroadcastTx: gorpc.NewRPCFunc(func(tx txs.Wrapper) (*rpc.ResultBroadcastTx, error) { + BroadcastTx: server.NewRPCFunc(func(tx txs.Wrapper) (*rpc.ResultBroadcastTx, error) { receipt, err := service.Transactor().BroadcastTx(tx.Unwrap()) if err != nil { return nil, err @@ -73,14 +73,14 @@ func GetRoutes(service *rpc.Service, logger *logging.Logger) map[string]*gorpc.R }, nil }, "tx"), - SignTx: gorpc.NewRPCFunc(func(tx txs.Tx, concretePrivateAccounts []*acm.ConcretePrivateAccount) (*rpc.ResultSignTx, error) { + SignTx: server.NewRPCFunc(func(tx txs.Tx, concretePrivateAccounts []*acm.ConcretePrivateAccount) (*rpc.ResultSignTx, error) { tx, err := service.Transactor().SignTx(tx, acm.SigningAccounts(concretePrivateAccounts)) return &rpc.ResultSignTx{Tx: txs.Wrap(tx)}, err }, "tx,privAccounts"), // Simulated call - Call: gorpc.NewRPCFunc(func(fromAddress, toAddress crypto.Address, data []byte) (*rpc.ResultCall, error) { + Call: server.NewRPCFunc(func(fromAddress, toAddress crypto.Address, data []byte) (*rpc.ResultCall, error) { call, err := service.Transactor().Call(service.State(), fromAddress, toAddress, data) if err != nil { return nil, err @@ -88,7 +88,7 @@ func GetRoutes(service *rpc.Service, logger *logging.Logger) map[string]*gorpc.R return &rpc.ResultCall{Call: *call}, nil }, "fromAddress,toAddress,data"), - CallCode: gorpc.NewRPCFunc(func(fromAddress crypto.Address, code, data []byte) (*rpc.ResultCall, error) { + CallCode: server.NewRPCFunc(func(fromAddress crypto.Address, code, data []byte) (*rpc.ResultCall, error) { call, err := service.Transactor().CallCode(service.State(), fromAddress, code, data) if err != nil { return nil, err @@ -97,17 +97,17 @@ func GetRoutes(service *rpc.Service, logger *logging.Logger) map[string]*gorpc.R }, "fromAddress,code,data"), // Events - Subscribe: gorpc.NewWSRPCFunc(func(wsCtx rpctypes.WSRPCContext, eventID string) (*rpc.ResultSubscribe, error) { + Subscribe: server.NewWSRPCFunc(func(wsCtx types.WSRPCContext, eventID string) (*rpc.ResultSubscribe, error) { subscriptionID, err := event.GenerateSubscriptionID() if err != nil { return nil, err } - ctx, cancel := context.WithTimeout(context.Background(), SubscriptionTimeoutSeconds*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), SubscriptionTimeout) defer cancel() err = service.Subscribe(ctx, subscriptionID, eventID, func(resultEvent *rpc.ResultEvent) bool { - keepAlive := wsCtx.TryWriteRPCResponse(rpctypes.NewRPCSuccessResponse(AminoCodec, + keepAlive := wsCtx.TryWriteRPCResponse(types.NewRPCSuccessResponse( EventResponseID(wsCtx.Request.ID, eventID), resultEvent)) if !keepAlive { logger.InfoMsg("dropping subscription because could not write to websocket", @@ -125,8 +125,8 @@ func GetRoutes(service *rpc.Service, logger *logging.Logger) map[string]*gorpc.R }, nil }, "eventID"), - Unsubscribe: gorpc.NewWSRPCFunc(func(wsCtx rpctypes.WSRPCContext, subscriptionID string) (*rpc.ResultUnsubscribe, error) { - ctx, cancel := context.WithTimeout(context.Background(), SubscriptionTimeoutSeconds*time.Second) + Unsubscribe: server.NewWSRPCFunc(func(wsCtx types.WSRPCContext, subscriptionID string) (*rpc.ResultUnsubscribe, error) { + ctx, cancel := context.WithTimeout(context.Background(), SubscriptionTimeout) defer cancel() // Since our model uses a random subscription ID per request we just drop all matching requests err := service.Unsubscribe(ctx, subscriptionID) @@ -139,42 +139,42 @@ func GetRoutes(service *rpc.Service, logger *logging.Logger) map[string]*gorpc.R }, "subscriptionID"), // Status - Status: gorpc.NewRPCFunc(service.Status, ""), - NetInfo: gorpc.NewRPCFunc(service.NetInfo, ""), + Status: server.NewRPCFunc(service.Status, ""), + NetInfo: server.NewRPCFunc(service.NetInfo, ""), // Accounts - ListAccounts: gorpc.NewRPCFunc(func() (*rpc.ResultListAccounts, error) { + ListAccounts: server.NewRPCFunc(func() (*rpc.ResultListAccounts, error) { return service.ListAccounts(func(acm.Account) bool { return true }) }, ""), - GetAccount: gorpc.NewRPCFunc(service.GetAccount, "address"), - GetStorage: gorpc.NewRPCFunc(service.GetStorage, "address,key"), - DumpStorage: gorpc.NewRPCFunc(service.DumpStorage, "address"), - GetAccountHuman: gorpc.NewRPCFunc(service.GetAccountHumanReadable, "address"), + GetAccount: server.NewRPCFunc(service.GetAccount, "address"), + GetStorage: server.NewRPCFunc(service.GetStorage, "address,key"), + DumpStorage: server.NewRPCFunc(service.DumpStorage, "address"), + GetAccountHuman: server.NewRPCFunc(service.GetAccountHumanReadable, "address"), // Blockchain - Genesis: gorpc.NewRPCFunc(service.Genesis, ""), - ChainID: gorpc.NewRPCFunc(service.ChainId, ""), - ListBlocks: gorpc.NewRPCFunc(service.ListBlocks, "minHeight,maxHeight"), - GetBlock: gorpc.NewRPCFunc(service.GetBlock, "height"), + Genesis: server.NewRPCFunc(service.Genesis, ""), + ChainID: server.NewRPCFunc(service.ChainId, ""), + ListBlocks: server.NewRPCFunc(service.ListBlocks, "minHeight,maxHeight"), + GetBlock: server.NewRPCFunc(service.GetBlock, "height"), // Consensus - ListUnconfirmedTxs: gorpc.NewRPCFunc(service.ListUnconfirmedTxs, "maxTxs"), - ListValidators: gorpc.NewRPCFunc(service.ListValidators, ""), - DumpConsensusState: gorpc.NewRPCFunc(service.DumpConsensusState, ""), + ListUnconfirmedTxs: server.NewRPCFunc(service.ListUnconfirmedTxs, "maxTxs"), + ListValidators: server.NewRPCFunc(service.ListValidators, ""), + DumpConsensusState: server.NewRPCFunc(service.DumpConsensusState, ""), // Names - GetName: gorpc.NewRPCFunc(service.GetName, "name"), - ListNames: gorpc.NewRPCFunc(func() (*rpc.ResultListNames, error) { + GetName: server.NewRPCFunc(service.GetName, "name"), + ListNames: server.NewRPCFunc(func() (*rpc.ResultListNames, error) { return service.ListNames(func(*execution.NameRegEntry) bool { return true }) }, ""), // Private account - GeneratePrivateAccount: gorpc.NewRPCFunc(service.GeneratePrivateAccount, ""), + GeneratePrivateAccount: server.NewRPCFunc(service.GeneratePrivateAccount, ""), } } diff --git a/rpc/tm/server.go b/rpc/tm/server.go index 8a4239ab69dcd35ad74c87984b585c3da8ee207a..db6cd332ddf2039c9f9f69027816495ec370b84d 100644 --- a/rpc/tm/server.go +++ b/rpc/tm/server.go @@ -23,7 +23,7 @@ import ( "github.com/hyperledger/burrow/logging" "github.com/hyperledger/burrow/logging/structure" "github.com/hyperledger/burrow/rpc" - "github.com/tendermint/tendermint/rpc/lib/server" + "github.com/hyperledger/burrow/rpc/tm/lib/server" ) func StartServer(service *rpc.Service, pattern, listenAddress string, emitter event.Emitter, @@ -32,11 +32,10 @@ func StartServer(service *rpc.Service, pattern, listenAddress string, emitter ev logger = logger.With(structure.ComponentKey, "RPC_TM") routes := GetRoutes(service, logger) mux := http.NewServeMux() - wm := rpcserver.NewWebsocketManager(routes, AminoCodec, rpcserver.EventSubscriber(tendermint.SubscribableAsEventBus(emitter))) + wm := server.NewWebsocketManager(routes, logger, server.EventSubscriber(tendermint.SubscribableAsEventBus(emitter))) mux.HandleFunc(pattern, wm.WebsocketHandler) - tmLogger := tendermint.NewLogger(logger) - rpcserver.RegisterRPCFuncs(mux, routes, AminoCodec, tmLogger) - listener, err := rpcserver.StartHTTPServer(listenAddress, mux, tmLogger) + server.RegisterRPCFuncs(mux, routes, logger) + listener, err := server.StartHTTPServer(listenAddress, mux, logger) if err != nil { return nil, err } diff --git a/rpc/tm/wire.go b/rpc/tm/wire.go deleted file mode 100644 index 7e7782e009db1fafa13e2e7f34cad4846ae5d5d3..0000000000000000000000000000000000000000 --- a/rpc/tm/wire.go +++ /dev/null @@ -1,14 +0,0 @@ -package tm - -import ( - "github.com/tendermint/go-amino" - "github.com/tendermint/tendermint/rpc/core/types" -) - -var AminoCodec = amino.NewCodec() - -func init() { - //types.RegisterEvidences(AminoCodec) - //crypto.RegisterAmino(AminoCodec) - core_types.RegisterAmino(AminoCodec) -} diff --git a/rpc/wire.go b/rpc/wire.go deleted file mode 100644 index 088fce04a37fb2b7309e6a67c7b2ba99b9b093c5..0000000000000000000000000000000000000000 --- a/rpc/wire.go +++ /dev/null @@ -1,14 +0,0 @@ -package rpc - -import ( - "github.com/tendermint/go-amino" - "github.com/tendermint/go-crypto" -) - -var cdc = amino.NewCodec() - -func init() { - //types.RegisterEvidences(AminoCodec) - crypto.RegisterAmino(cdc) - //core_types.RegisterAmino(AminoCodec) -}