mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-16 14:41:21 +00:00
support historical abci queries (Refs #482)
This commit is contained in:
@ -69,10 +69,14 @@ func (c *HTTP) ABCIInfo() (*ctypes.ResultABCIInfo, error) {
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *HTTP) ABCIQuery(path string, data data.Bytes, prove bool) (*ctypes.ResultABCIQuery, error) {
|
func (c *HTTP) ABCIQuery(path string, data data.Bytes) (*ctypes.ResultABCIQuery, error) {
|
||||||
|
return c.ABCIQueryWithOptions(path, data, DefaultABCIQueryOptions())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *HTTP) ABCIQueryWithOptions(path string, data data.Bytes, opts ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) {
|
||||||
result := new(ctypes.ResultABCIQuery)
|
result := new(ctypes.ResultABCIQuery)
|
||||||
_, err := c.rpc.Call("abci_query",
|
_, err := c.rpc.Call("abci_query",
|
||||||
map[string]interface{}{"path": path, "data": data, "prove": prove},
|
map[string]interface{}{"path": path, "data": data, "height": opts.Height, "prove": opts.Prove},
|
||||||
result)
|
result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "ABCIQuery")
|
return nil, errors.Wrap(err, "ABCIQuery")
|
||||||
|
@ -31,7 +31,8 @@ import (
|
|||||||
type ABCIClient interface {
|
type ABCIClient interface {
|
||||||
// reading from abci app
|
// reading from abci app
|
||||||
ABCIInfo() (*ctypes.ResultABCIInfo, error)
|
ABCIInfo() (*ctypes.ResultABCIInfo, error)
|
||||||
ABCIQuery(path string, data data.Bytes, prove bool) (*ctypes.ResultABCIQuery, error)
|
ABCIQuery(path string, data data.Bytes) (*ctypes.ResultABCIQuery, error)
|
||||||
|
ABCIQueryWithOptions(path string, data data.Bytes, opts ABCIQueryOptions) (*ctypes.ResultABCIQuery, error)
|
||||||
|
|
||||||
// writing to abci app
|
// writing to abci app
|
||||||
BroadcastTxCommit(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error)
|
BroadcastTxCommit(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error)
|
||||||
|
@ -57,8 +57,12 @@ func (c Local) ABCIInfo() (*ctypes.ResultABCIInfo, error) {
|
|||||||
return core.ABCIInfo()
|
return core.ABCIInfo()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Local) ABCIQuery(path string, data data.Bytes, prove bool) (*ctypes.ResultABCIQuery, error) {
|
func (c Local) ABCIQuery(path string, data data.Bytes) (*ctypes.ResultABCIQuery, error) {
|
||||||
return core.ABCIQuery(path, data, prove)
|
return c.ABCIQueryWithOptions(path, data, DefaultABCIQueryOptions())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Local) ABCIQueryWithOptions(path string, data data.Bytes, opts ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) {
|
||||||
|
return core.ABCIQuery(path, data, opts.Height, opts.Prove)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Local) BroadcastTxCommit(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) {
|
func (c Local) BroadcastTxCommit(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) {
|
||||||
|
@ -24,8 +24,12 @@ func (a ABCIApp) ABCIInfo() (*ctypes.ResultABCIInfo, error) {
|
|||||||
return &ctypes.ResultABCIInfo{a.App.Info(abci.RequestInfo{version.Version})}, nil
|
return &ctypes.ResultABCIInfo{a.App.Info(abci.RequestInfo{version.Version})}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a ABCIApp) ABCIQuery(path string, data data.Bytes, prove bool) (*ctypes.ResultABCIQuery, error) {
|
func (a ABCIApp) ABCIQuery(path string, data data.Bytes) (*ctypes.ResultABCIQuery, error) {
|
||||||
q := a.App.Query(abci.RequestQuery{data, path, 0, prove})
|
return a.ABCIQueryWithOptions(path, data, client.DefaultABCIQueryOptions())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a ABCIApp) ABCIQueryWithOptions(path string, data data.Bytes, opts client.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) {
|
||||||
|
q := a.App.Query(abci.RequestQuery{data, path, opts.Height, opts.Prove})
|
||||||
return &ctypes.ResultABCIQuery{q.Result()}, nil
|
return &ctypes.ResultABCIQuery{q.Result()}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,8 +83,12 @@ func (m ABCIMock) ABCIInfo() (*ctypes.ResultABCIInfo, error) {
|
|||||||
return &ctypes.ResultABCIInfo{res.(abci.ResponseInfo)}, nil
|
return &ctypes.ResultABCIInfo{res.(abci.ResponseInfo)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m ABCIMock) ABCIQuery(path string, data data.Bytes, prove bool) (*ctypes.ResultABCIQuery, error) {
|
func (m ABCIMock) ABCIQuery(path string, data data.Bytes) (*ctypes.ResultABCIQuery, error) {
|
||||||
res, err := m.Query.GetResponse(QueryArgs{path, data, prove})
|
return m.ABCIQueryWithOptions(path, data, client.DefaultABCIQueryOptions())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m ABCIMock) ABCIQueryWithOptions(path string, data data.Bytes, opts client.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) {
|
||||||
|
res, err := m.Query.GetResponse(QueryArgs{path, data, opts.Height, opts.Prove})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -133,6 +141,7 @@ func (r *ABCIRecorder) _assertABCIClient() client.ABCIClient {
|
|||||||
type QueryArgs struct {
|
type QueryArgs struct {
|
||||||
Path string
|
Path string
|
||||||
Data data.Bytes
|
Data data.Bytes
|
||||||
|
Height uint64
|
||||||
Prove bool
|
Prove bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,11 +159,15 @@ func (r *ABCIRecorder) ABCIInfo() (*ctypes.ResultABCIInfo, error) {
|
|||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ABCIRecorder) ABCIQuery(path string, data data.Bytes, prove bool) (*ctypes.ResultABCIQuery, error) {
|
func (r *ABCIRecorder) ABCIQuery(path string, data data.Bytes) (*ctypes.ResultABCIQuery, error) {
|
||||||
res, err := r.Client.ABCIQuery(path, data, prove)
|
return r.ABCIQueryWithOptions(path, data, client.DefaultABCIQueryOptions())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ABCIRecorder) ABCIQueryWithOptions(path string, data data.Bytes, opts client.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) {
|
||||||
|
res, err := r.Client.ABCIQueryWithOptions(path, data, opts)
|
||||||
r.addCall(Call{
|
r.addCall(Call{
|
||||||
Name: "abci_query",
|
Name: "abci_query",
|
||||||
Args: QueryArgs{path, data, prove},
|
Args: QueryArgs{path, data, opts.Height, opts.Prove},
|
||||||
Response: res,
|
Response: res,
|
||||||
Error: err,
|
Error: err,
|
||||||
})
|
})
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/tendermint/abci/example/dummy"
|
"github.com/tendermint/abci/example/dummy"
|
||||||
abci "github.com/tendermint/abci/types"
|
abci "github.com/tendermint/abci/types"
|
||||||
data "github.com/tendermint/go-wire/data"
|
data "github.com/tendermint/go-wire/data"
|
||||||
|
"github.com/tendermint/tendermint/rpc/client"
|
||||||
"github.com/tendermint/tendermint/rpc/client/mock"
|
"github.com/tendermint/tendermint/rpc/client/mock"
|
||||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/types"
|
||||||
@ -50,7 +51,7 @@ func TestABCIMock(t *testing.T) {
|
|||||||
assert.Equal("foobar", err.Error())
|
assert.Equal("foobar", err.Error())
|
||||||
|
|
||||||
// query always returns the response
|
// query always returns the response
|
||||||
query, err := m.ABCIQuery("/", nil, false)
|
query, err := m.ABCIQueryWithOptions("/", nil, client.ABCIQueryOptions{Prove: false})
|
||||||
require.Nil(err)
|
require.Nil(err)
|
||||||
require.NotNil(query)
|
require.NotNil(query)
|
||||||
assert.EqualValues(key, query.Key)
|
assert.EqualValues(key, query.Key)
|
||||||
@ -92,7 +93,7 @@ func TestABCIRecorder(t *testing.T) {
|
|||||||
require.Equal(0, len(r.Calls))
|
require.Equal(0, len(r.Calls))
|
||||||
|
|
||||||
r.ABCIInfo()
|
r.ABCIInfo()
|
||||||
r.ABCIQuery("path", data.Bytes("data"), true)
|
r.ABCIQueryWithOptions("path", data.Bytes("data"), client.ABCIQueryOptions{Prove: true})
|
||||||
require.Equal(2, len(r.Calls))
|
require.Equal(2, len(r.Calls))
|
||||||
|
|
||||||
info := r.Calls[0]
|
info := r.Calls[0]
|
||||||
@ -164,7 +165,7 @@ func TestABCIApp(t *testing.T) {
|
|||||||
assert.True(res.DeliverTx.Code.IsOK())
|
assert.True(res.DeliverTx.Code.IsOK())
|
||||||
|
|
||||||
// check the key
|
// check the key
|
||||||
qres, err := m.ABCIQuery("/key", data.Bytes(key), false)
|
qres, err := m.ABCIQueryWithOptions("/key", data.Bytes(key), client.ABCIQueryOptions{Prove: false})
|
||||||
require.Nil(err)
|
require.Nil(err)
|
||||||
assert.EqualValues(value, qres.Value)
|
assert.EqualValues(value, qres.Value)
|
||||||
}
|
}
|
||||||
|
@ -84,8 +84,12 @@ func (c Client) ABCIInfo() (*ctypes.ResultABCIInfo, error) {
|
|||||||
return core.ABCIInfo()
|
return core.ABCIInfo()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Client) ABCIQuery(path string, data data.Bytes, prove bool) (*ctypes.ResultABCIQuery, error) {
|
func (c Client) ABCIQuery(path string, data data.Bytes) (*ctypes.ResultABCIQuery, error) {
|
||||||
return core.ABCIQuery(path, data, prove)
|
return c.ABCIQueryWithOptions(path, data, client.DefaultABCIQueryOptions())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Client) ABCIQueryWithOptions(path string, data data.Bytes, opts client.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) {
|
||||||
|
return core.ABCIQuery(path, data, opts.Height, opts.Prove)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Client) BroadcastTxCommit(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) {
|
func (c Client) BroadcastTxCommit(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) {
|
||||||
|
@ -98,6 +98,23 @@ func TestGenesisAndValidators(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestABCIQuery(t *testing.T) {
|
||||||
|
for i, c := range GetClients() {
|
||||||
|
// write something
|
||||||
|
k, v, tx := MakeTxKV()
|
||||||
|
bres, err := c.BroadcastTxCommit(tx)
|
||||||
|
require.Nil(t, err, "%d: %+v", i, err)
|
||||||
|
apph := bres.Height + 1 // this is where the tx will be applied to the state
|
||||||
|
|
||||||
|
// wait before querying
|
||||||
|
client.WaitForHeight(c, apph, nil)
|
||||||
|
qres, err := c.ABCIQuery("/key", k)
|
||||||
|
if assert.Nil(t, err) && assert.True(t, qres.Code.IsOK()) {
|
||||||
|
assert.EqualValues(t, v, qres.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Make some app checks
|
// Make some app checks
|
||||||
func TestAppCalls(t *testing.T) {
|
func TestAppCalls(t *testing.T) {
|
||||||
assert, require := assert.New(t), require.New(t)
|
assert, require := assert.New(t), require.New(t)
|
||||||
@ -124,7 +141,7 @@ func TestAppCalls(t *testing.T) {
|
|||||||
|
|
||||||
// wait before querying
|
// wait before querying
|
||||||
client.WaitForHeight(c, apph, nil)
|
client.WaitForHeight(c, apph, nil)
|
||||||
qres, err := c.ABCIQuery("/key", k, false)
|
qres, err := c.ABCIQueryWithOptions("/key", k, client.ABCIQueryOptions{Prove: false})
|
||||||
if assert.Nil(err) && assert.True(qres.Code.IsOK()) {
|
if assert.Nil(err) && assert.True(qres.Code.IsOK()) {
|
||||||
// assert.Equal(k, data.GetKey()) // only returned for proofs
|
// assert.Equal(k, data.GetKey()) // only returned for proofs
|
||||||
assert.EqualValues(v, qres.Value)
|
assert.EqualValues(v, qres.Value)
|
||||||
@ -172,7 +189,7 @@ func TestAppCalls(t *testing.T) {
|
|||||||
assert.Equal(block.Block.LastCommit, commit2.Commit)
|
assert.Equal(block.Block.LastCommit, commit2.Commit)
|
||||||
|
|
||||||
// and we got a proof that works!
|
// and we got a proof that works!
|
||||||
pres, err := c.ABCIQuery("/key", k, true)
|
pres, err := c.ABCIQueryWithOptions("/key", k, client.ABCIQueryOptions{Prove: true})
|
||||||
if assert.Nil(err) && assert.True(pres.Code.IsOK()) {
|
if assert.Nil(err) && assert.True(pres.Code.IsOK()) {
|
||||||
proof, err := iavl.ReadProof(pres.Proof)
|
proof, err := iavl.ReadProof(pres.Proof)
|
||||||
if assert.Nil(err) {
|
if assert.Nil(err) {
|
||||||
|
13
rpc/client/types.go
Normal file
13
rpc/client/types.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package client
|
||||||
|
|
||||||
|
// ABCIQueryOptions can be used to provide options for ABCIQuery call other
|
||||||
|
// than the DefaultABCIQueryOptions.
|
||||||
|
type ABCIQueryOptions struct {
|
||||||
|
Height uint64
|
||||||
|
Prove bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultABCIQueryOptions are latest height (0) and prove equal to true.
|
||||||
|
func DefaultABCIQueryOptions() ABCIQueryOptions {
|
||||||
|
return ABCIQueryOptions{Height: 0, Prove: true}
|
||||||
|
}
|
@ -45,11 +45,13 @@ import (
|
|||||||
// |-----------+--------+---------+----------+---------------------------------------|
|
// |-----------+--------+---------+----------+---------------------------------------|
|
||||||
// | path | string | false | false | Path to the data ("/a/b/c") |
|
// | path | string | false | false | Path to the data ("/a/b/c") |
|
||||||
// | data | []byte | false | true | Data |
|
// | data | []byte | false | true | Data |
|
||||||
|
// | height | uint64 | 0 | false | Height (0 means latest) |
|
||||||
// | prove | bool | false | false | Include a proof of the data inclusion |
|
// | prove | bool | false | false | Include a proof of the data inclusion |
|
||||||
func ABCIQuery(path string, data data.Bytes, prove bool) (*ctypes.ResultABCIQuery, error) {
|
func ABCIQuery(path string, data data.Bytes, height uint64, prove bool) (*ctypes.ResultABCIQuery, error) {
|
||||||
resQuery, err := proxyAppQuery.QuerySync(abci.RequestQuery{
|
resQuery, err := proxyAppQuery.QuerySync(abci.RequestQuery{
|
||||||
Path: path,
|
Path: path,
|
||||||
Data: data,
|
Data: data,
|
||||||
|
Height: height,
|
||||||
Prove: prove,
|
Prove: prove,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -29,7 +29,7 @@ var Routes = map[string]*rpc.RPCFunc{
|
|||||||
"broadcast_tx_async": rpc.NewRPCFunc(BroadcastTxAsync, "tx"),
|
"broadcast_tx_async": rpc.NewRPCFunc(BroadcastTxAsync, "tx"),
|
||||||
|
|
||||||
// abci API
|
// abci API
|
||||||
"abci_query": rpc.NewRPCFunc(ABCIQuery, "path,data,prove"),
|
"abci_query": rpc.NewRPCFunc(ABCIQuery, "path,data,height,prove"),
|
||||||
"abci_info": rpc.NewRPCFunc(ABCIInfo, ""),
|
"abci_info": rpc.NewRPCFunc(ABCIInfo, ""),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user