diff --git a/packages/go-kosu/CHANGELOG.md b/packages/go-kosu/CHANGELOG.md index c2c8c13bd..c09793908 100644 --- a/packages/go-kosu/CHANGELOG.md +++ b/packages/go-kosu/CHANGELOG.md @@ -2,6 +2,7 @@ ## master +- Add GetBlocks RPC endpoint - Fix wrong RPC remote address in lite mode ## v0.4.0 diff --git a/packages/go-kosu/docs/kosu_rpc.md b/packages/go-kosu/docs/kosu_rpc.md index 8f92cde80..e676e97a2 100644 --- a/packages/go-kosu/docs/kosu_rpc.md +++ b/packages/go-kosu/docs/kosu_rpc.md @@ -112,6 +112,88 @@ curl -X POST localhost:14341 \ ] ``` +### _GetBlocks_ + +GetBlocks gets one or more blocks given a list of heights. +It will fail if there are at least one invalid or non-existing block height in the parameters. + +_Method:_ + +- `kosu_getBlocks` + +_Parameters:_ + +- `heights` - `Array`(_int64_) + +_Returns:_ + +- `blocks` - `Array`([Block](https://godoc.org/github.com/tendermint/tendermint/types#Block)) + +#### cURL Example + +```bash +# The following will request the block with height 1 +curl -X POST localhost:14341 \ + --data '{"jsonrpc":"2.0", "id": 1, "method": "kosu_getBlocks", "params": [[1]]}' \ + -H 'Content-Type: application/json' +``` + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": [ + { + "header": { + "version": { + "block": 10, + "app": 0 + }, + "chain_id": "kosu-chain-6ETgBz", + "height": 1, + "time": "2019-10-15T08:25:58.01874923Z", + "num_txs": 1, + "total_txs": 1, + "last_block_id": { + "hash": "", + "parts": { + "total": 0, + "hash": "" + } + }, + "last_commit_hash": "", + "data_hash": "ACB36F347EAACE6E496058659C319C5C3633E9C767FA3A7FC7BB5A76472614B6", + "validators_hash": "9FD0575A3E1F26E9C21C69A885E096A55D546BAF2273EF22AB381FB5CE509100", + "next_validators_hash": "9FD0575A3E1F26E9C21C69A885E096A55D546BAF2273EF22AB381FB5CE509100", + "consensus_hash": "048091BC7DDC283F77BFBF91D73C44DA58C3DF8A9CBC867405D8B7F3DAADA22F", + "app_hash": "", + "last_results_hash": "", + "evidence_hash": "", + "proposer_address": "934211FEB7AA63390DDABD2CF02D042F6B4BCD7B" + }, + "data": { + "txs": [ + "Q21RS0lERWR0NUlBdUFGelFxczVhUE1oRGdlLzdIOEtRdVpFaDVCMEVtN1JQTkVURWtDY1JKeFN2TEMrVURmMWovQWFCRDY0dFdCSFpROWtjYXU5OXg3REw4K244MzdBSUhja252aUtGbXBwbFlKMG1Oc1daYlZvRFBjNndFTjh6R1VKdXZNS0VoSUtFQklPQ0FFUXpkQUNHTmZRQWlDZ2pRWT0=" + ] + }, + "evidence": { + "evidence": null + }, + "last_commit": { + "block_id": { + "hash": "", + "parts": { + "total": 0, + "hash": "" + } + }, + "precommits": null + } + } + ] +} +``` + ### _LatestHeight_ LatestHeight returns the height of the best known block. diff --git a/packages/go-kosu/rpc/rpc_test.go b/packages/go-kosu/rpc/rpc_test.go index 56cc654ca..27e4833d7 100644 --- a/packages/go-kosu/rpc/rpc_test.go +++ b/packages/go-kosu/rpc/rpc_test.go @@ -13,6 +13,8 @@ import ( "github.com/ParadigmFoundation/kosu-monorepo/packages/go-kosu/abci/types" "github.com/ParadigmFoundation/kosu-monorepo/packages/go-kosu/tests" + rpctypes "github.com/tendermint/tendermint/rpc/core/types" + tmtypes "github.com/tendermint/tendermint/types" db "github.com/tendermint/tm-db" ) @@ -41,6 +43,7 @@ func TestRPC(t *testing.T) { {"RebalancePeriod", RebalancePeriod}, {"NewRebalances", NewRebalances}, {"NumberPosters", NumberPosters}, + {"GetBlocks", GetBlocks}, } for _, test := range cases { @@ -191,3 +194,23 @@ func NumberPosters(t *testing.T, app *abci.App, _ *abci.Client, rpcClient *rpc.C assert.EqualValues(t, len(addresses), num) } + +func GetBlocks(t *testing.T, app *abci.App, _ *abci.Client, rpcClient *rpc.Client) { + t.Run("First block", func(t *testing.T) { + waitForNewBlock(t, rpcClient) + + var blocks []*tmtypes.Block + err := rpcClient.Call(&blocks, "kosu_getBlocks", []int64{1}) + require.NoError(t, err) + require.Len(t, blocks, 1) + block := blocks[0] + assert.EqualValues(t, 1, block.Height) + }) + t.Run("non-existent block number", func(t *testing.T) { + var blocks []*rpctypes.ResultBlock + err := rpcClient.Call(&blocks, "kosu_getBlocks", []int64{1, 2, 3, 4, 9999}) + require.Error(t, err) + assert.Contains(t, err.Error(), "Height must be less than or equal to the current blockchain height") + assert.Empty(t, blocks) + }) +} diff --git a/packages/go-kosu/rpc/service.go b/packages/go-kosu/rpc/service.go index 220c2f840..4e3c74e9a 100644 --- a/packages/go-kosu/rpc/service.go +++ b/packages/go-kosu/rpc/service.go @@ -923,3 +923,98 @@ func (s *Service) RemainingLimit() (uint64, error) { return num, nil } + +/* +GetBlocks gets one or more blocks given a list of heights. +It will fail if there are at least one invalid or non-existing block height in the parameters. + +_Method:_ + +- `kosu_getBlocks` + +_Parameters:_ + +- `heights` - `Array`(_int64_) + +_Returns:_ + +- `blocks` - `Array`([Block](https://godoc.org/github.com/tendermint/tendermint/types#Block)) + +#### cURL Example + +```bash +# The following will request the block with height 1 +curl -X POST localhost:14341 \ + --data '{"jsonrpc":"2.0", "id": 1, "method": "kosu_getBlocks", "params": [[1]]}' \ + -H 'Content-Type: application/json' +``` + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": [ + { + "header": { + "version": { + "block": 10, + "app": 0 + }, + "chain_id": "kosu-chain-6ETgBz", + "height": 1, + "time": "2019-10-15T08:25:58.01874923Z", + "num_txs": 1, + "total_txs": 1, + "last_block_id": { + "hash": "", + "parts": { + "total": 0, + "hash": "" + } + }, + "last_commit_hash": "", + "data_hash": "ACB36F347EAACE6E496058659C319C5C3633E9C767FA3A7FC7BB5A76472614B6", + "validators_hash": "9FD0575A3E1F26E9C21C69A885E096A55D546BAF2273EF22AB381FB5CE509100", + "next_validators_hash": "9FD0575A3E1F26E9C21C69A885E096A55D546BAF2273EF22AB381FB5CE509100", + "consensus_hash": "048091BC7DDC283F77BFBF91D73C44DA58C3DF8A9CBC867405D8B7F3DAADA22F", + "app_hash": "", + "last_results_hash": "", + "evidence_hash": "", + "proposer_address": "934211FEB7AA63390DDABD2CF02D042F6B4BCD7B" + }, + "data": { + "txs": [ + "Q21RS0lERWR0NUlBdUFGelFxczVhUE1oRGdlLzdIOEtRdVpFaDVCMEVtN1JQTkVURWtDY1JKeFN2TEMrVURmMWovQWFCRDY0dFdCSFpROWtjYXU5OXg3REw4K244MzdBSUhja252aUtGbXBwbFlKMG1Oc1daYlZvRFBjNndFTjh6R1VKdXZNS0VoSUtFQklPQ0FFUXpkQUNHTmZRQWlDZ2pRWT0=" + ] + }, + "evidence": { + "evidence": null + }, + "last_commit": { + "block_id": { + "hash": "", + "parts": { + "total": 0, + "hash": "" + } + }, + "precommits": null + } + } + ] +} +``` + +*/ +func (s *Service) GetBlocks(heights []int64) ([]*tmtypes.Block, error) { + blocks := make([]*tmtypes.Block, len(heights)) + for i, height := range heights { + result, err := s.abci.Block(&height) + if err != nil { + return nil, err + + } + blocks[i] = result.Block + } + return blocks, nil +}