rpc: /block_results fix docs + write test + restructure response (#3615)

BREAKING

Example response:

```json
{
  "jsonrpc": "2.0",
  "id": "",
  "result": {
    "height": "2109",
    "txs_results": null,
    "begin_block_events": null,
    "end_block_events": null,
    "validator_updates": null,
    "consensus_param_updates": null
  }
}
```

Old result consisted of ABCIResponses struct and height. Exposing
internal ABCI structures (which we store in state package) in RPC seems
bad to me for the following reasons:

1) high risk of breaking the API when somebody changes internal structs
(HAPPENED HERE!)
2) RPC is aware of ABCI, which I'm not sure we want
This commit is contained in:
Anton Kaliaev
2019-11-14 13:34:35 +04:00
committed by GitHub
parent 7bc5e1aa00
commit 59da313bc0
13 changed files with 287 additions and 90 deletions
+2 -2
View File
@@ -233,9 +233,9 @@ func TestAppCalls(t *testing.T) {
blockResults, err := c.BlockResults(&txh)
require.Nil(err, "%d: %+v", i, err)
assert.Equal(txh, blockResults.Height)
if assert.Equal(1, len(blockResults.Results.DeliverTx)) {
if assert.Equal(1, len(blockResults.TxsResults)) {
// check success code
assert.EqualValues(0, blockResults.Results.DeliverTx[0].Code)
assert.EqualValues(0, blockResults.TxsResults[0].Code)
}
// check blockchain info, now that we know there is info
+8 -5
View File
@@ -124,11 +124,14 @@ func BlockResults(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultBlockR
return nil, err
}
res := &ctypes.ResultBlockResults{
Height: height,
Results: results,
}
return res, nil
return &ctypes.ResultBlockResults{
Height: height,
TxsResults: results.DeliverTxs,
BeginBlockEvents: results.BeginBlock.Events,
EndBlockEvents: results.EndBlock.Events,
ValidatorUpdates: results.EndBlock.ValidatorUpdates,
ConsensusParamUpdates: results.EndBlock.ConsensusParamUpdates,
}, nil
}
func getHeight(currentHeight int64, heightPtr *int64) (int64, error) {
+64 -1
View File
@@ -4,11 +4,18 @@ import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
rpctypes "github.com/tendermint/tendermint/rpc/lib/types"
sm "github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/types"
dbm "github.com/tendermint/tm-db"
)
func TestBlockchainInfo(t *testing.T) {
cases := []struct {
min, max int64
height int64
@@ -54,5 +61,61 @@ func TestBlockchainInfo(t *testing.T) {
require.Equal(t, 1+max-min, c.resultLength, caseString)
}
}
}
func TestBlockResults(t *testing.T) {
results := &sm.ABCIResponses{
DeliverTxs: []*abci.ResponseDeliverTx{
{Code: 0, Data: []byte{0x01}, Log: "ok"},
{Code: 0, Data: []byte{0x02}, Log: "ok"},
{Code: 1, Log: "not ok"},
},
EndBlock: &abci.ResponseEndBlock{},
BeginBlock: &abci.ResponseBeginBlock{},
}
stateDB = dbm.NewMemDB()
sm.SaveABCIResponses(stateDB, 100, results)
blockStore = mockBlockStore{height: 100}
testCases := []struct {
height int64
wantErr bool
wantRes *ctypes.ResultBlockResults
}{
{-1, true, nil},
{0, true, nil},
{101, true, nil},
{100, false, &ctypes.ResultBlockResults{
Height: 100,
TxsResults: results.DeliverTxs,
BeginBlockEvents: results.BeginBlock.Events,
EndBlockEvents: results.EndBlock.Events,
ValidatorUpdates: results.EndBlock.ValidatorUpdates,
ConsensusParamUpdates: results.EndBlock.ConsensusParamUpdates,
}},
}
for _, tc := range testCases {
res, err := BlockResults(&rpctypes.Context{}, &tc.height)
if tc.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, tc.wantRes, res)
}
}
}
type mockBlockStore struct {
height int64
}
func (store mockBlockStore) Height() int64 { return store.height }
func (mockBlockStore) LoadBlockMeta(height int64) *types.BlockMeta { return nil }
func (mockBlockStore) LoadBlock(height int64) *types.Block { return nil }
func (mockBlockStore) LoadBlockPart(height int64, index int) *types.Part { return nil }
func (mockBlockStore) LoadBlockCommit(height int64) *types.Commit { return nil }
func (mockBlockStore) LoadSeenCommit(height int64) *types.Commit { return nil }
func (mockBlockStore) SaveBlock(block *types.Block, blockParts *types.PartSet, seenCommit *types.Commit) {
}
+6 -3
View File
@@ -9,7 +9,6 @@ import (
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/tendermint/tendermint/p2p"
"github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/types"
)
@@ -38,8 +37,12 @@ type ResultCommit struct {
// ABCI results from a block
type ResultBlockResults struct {
Height int64 `json:"height"`
Results *state.ABCIResponses `json:"results"`
Height int64 `json:"height"`
TxsResults []*abci.ResponseDeliverTx `json:"txs_results"`
BeginBlockEvents []abci.Event `json:"begin_block_events"`
EndBlockEvents []abci.Event `json:"end_block_events"`
ValidatorUpdates []abci.ValidatorUpdate `json:"validator_updates"`
ConsensusParamUpdates *abci.ConsensusParams `json:"consensus_param_updates"`
}
// NewResultCommit is a helper to initialize the ResultCommit with
+170 -55
View File
@@ -1405,55 +1405,168 @@ definitions:
type: "string"
example: ""
result:
type: "object"
required:
- "height"
- "results"
properties:
height:
type: "string"
example: "12"
results:
required:
- "deliver_tx"
- "end_block"
- "begin_block"
properties:
deliver_tx:
type: "array"
x-nullable: true
items:
txs_results:
type: "array"
x-nullable: true
items:
type: "object"
properties:
code:
type: "string"
example: "0"
data:
type: "string"
example: ""
log:
type: "string"
example: "not enough gas"
info:
type: "string"
example: ""
gasWanted:
type: "string"
example: "100"
gasUsed:
type: "string"
example: "100"
events:
type: "array"
x-nullable: true
items:
type: "object"
properties:
type:
type: "string"
example: "app"
attributes:
type: "array"
x-nullable: false
items:
type: "object"
properties:
key:
type: "string"
example: "Y3JlYXRvcg=="
value:
type: "string"
example: "Q29zbW9zaGkgTmV0b3dva28="
codespace:
type: "string"
example: "ibc"
begin_block_events:
type: "array"
x-nullable: true
items:
type: "object"
properties:
type:
type: "string"
example: "app"
attributes:
type: "array"
x-nullable: false
items:
type: "object"
properties:
key:
type: "string"
example: "Y3JlYXRvcg=="
value:
type: "string"
example: "Q29zbW9zaGkgTmV0b3dva28="
end_block:
type: "array"
x-nullable: true
items:
type: "object"
properties:
type:
type: "string"
example: "app"
attributes:
type: "array"
x-nullable: false
items:
type: "object"
properties:
key:
type: "string"
example: "Y3JlYXRvcg=="
value:
type: "string"
example: "Q29zbW9zaGkgTmV0b3dva28="
validator_updates:
type: "array"
x-nullable: true
items:
type: "object"
properties:
pub_key:
type: "object"
required:
- "type"
- "value"
properties:
log:
type:
type: "string"
example: '[{"msg_index":"0","success":true,"log":""}]'
gasWanted:
example: "tendermint/PubKeyEd25519"
value:
type: "string"
example: "25629"
gasUsed:
type: "string"
example: "25629"
tags:
type: "array"
items:
type: "object"
properties:
key:
type: "string"
example: "YWN0aW9u"
value:
type: "string"
example: "c2VuZA=="
end_block:
required:
- "validator_updates"
properties: {}
type: "object"
begin_block:
properties: {}
type: "object"
example: "9tK9IT+FPdf2qm+5c2qaxi10sWP+3erWTKgftn2PaQM="
power:
type: "string"
example: "300"
consensus_param_updates:
type: "object"
type: "object"
x-nullable: true
required:
- "block"
- "evidence"
- "validator"
properties:
block:
type: "object"
required:
- "max_bytes"
- "max_gas"
- "time_iota_ms"
properties:
max_bytes:
type: "string"
example: "22020096"
max_gas:
type: "string"
example: "1000"
time_iota_ms:
type: "string"
example: "1000"
evidence:
type: "object"
required:
- "max_age"
properties:
max_age:
type: "string"
example: "100000"
validator:
type: "object"
required:
- "pub_key_types"
properties:
pub_key_types:
type: "array"
items:
type: "string"
example:
- "ed25519"
CommitResponse:
type: "object"
required:
@@ -1713,10 +1826,12 @@ definitions:
type: "string"
example: ""
result:
type: "object"
required:
- "genesis"
properties:
genesis:
type: "object"
required:
- "genesis_time"
- "chain_id"
@@ -1731,12 +1846,14 @@ definitions:
type: "string"
example: "cosmoshub-2"
consensus_params:
type: "object"
required:
- "block"
- "evidence"
- "validator"
properties:
block:
type: "object"
required:
- "max_bytes"
- "max_gas"
@@ -1744,23 +1861,23 @@ definitions:
properties:
max_bytes:
type: "string"
example: "200000"
example: "22020096"
max_gas:
type: "string"
example: "2000000"
example: "1000"
time_iota_ms:
type: "string"
example: "1000"
type: "object"
evidence:
type: "object"
required:
- "max_age"
properties:
max_age:
type: "string"
example: "1000000"
type: "object"
example: "100000"
validator:
type: "object"
required:
- "pub_key_types"
properties:
@@ -1770,8 +1887,6 @@ definitions:
type: "string"
example:
- "ed25519"
type: "object"
type: "object"
validators:
type: "array"
items:
@@ -1804,8 +1919,7 @@ definitions:
app_state:
properties: {}
type: "object"
type: "object"
type: "object"
DumpConsensusResponse:
type: object
required:
@@ -2236,6 +2350,7 @@ definitions:
type: "string"
example: ""
result:
type: "object"
required:
- "block_height"
- "consensus_params"
@@ -2244,12 +2359,14 @@ definitions:
type: "string"
example: "1313448"
consensus_params:
type: "object"
required:
- "block"
- "evidence"
- "validator"
properties:
block:
type: "object"
required:
- "max_bytes"
- "max_gas"
@@ -2257,23 +2374,23 @@ definitions:
properties:
max_bytes:
type: "string"
example: "200000"
example: "22020096"
max_gas:
type: "string"
example: "2000000"
example: "1000"
time_iota_ms:
type: "string"
example: "1000"
type: "object"
evidence:
type: "object"
required:
- "max_age"
properties:
max_age:
type: "string"
example: "1000000"
type: "object"
example: "100000"
validator:
type: "object"
required:
- "pub_key_types"
properties:
@@ -2283,9 +2400,7 @@ definitions:
type: "string"
example:
- "ed25519"
type: "object"
type: "object"
type: "object"
NumUnconfirmedTransactionsResponse:
type: object
required: