From 7b6810f9f68be630bd3a7b5a58be59fe45e57c1c Mon Sep 17 00:00:00 2001 From: Lee ByeongJun Date: Thu, 22 Aug 2024 11:48:25 +0900 Subject: [PATCH 1/5] abci height --- gno.land/pkg/gnoclient/mock_test.go | 9 ++++ tm2/pkg/bft/rpc/client/batch.go | 15 +++++++ tm2/pkg/bft/rpc/client/batch_test.go | 18 ++++++++ tm2/pkg/bft/rpc/client/client.go | 10 +++++ tm2/pkg/bft/rpc/client/client_test.go | 37 +++++++++++++++++ tm2/pkg/bft/rpc/client/e2e_test.go | 15 +++++++ tm2/pkg/bft/rpc/client/local.go | 4 ++ tm2/pkg/bft/rpc/client/types.go | 2 +- tm2/pkg/bft/rpc/core/abci.go | 59 +++++++++++++++++++++++++++ tm2/pkg/bft/rpc/core/routes.go | 5 ++- 10 files changed, 171 insertions(+), 3 deletions(-) diff --git a/gno.land/pkg/gnoclient/mock_test.go b/gno.land/pkg/gnoclient/mock_test.go index 64da62936c2..87a97b30d33 100644 --- a/gno.land/pkg/gnoclient/mock_test.go +++ b/gno.land/pkg/gnoclient/mock_test.go @@ -102,6 +102,7 @@ type ( mockABCIQuery func(path string, data []byte) (*ctypes.ResultABCIQuery, error) mockABCIInfo func() (*ctypes.ResultABCIInfo, error) mockABCIQueryWithOptions func(path string, data []byte, opts client.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) + mockABCIHeight func(height int64) (*ctypes.ResultABCIQuery, error) mockBroadcastTxAsync func(tx types.Tx) (*ctypes.ResultBroadcastTx, error) mockBroadcastTxSync func(tx types.Tx) (*ctypes.ResultBroadcastTx, error) mockGenesis func() (*ctypes.ResultGenesis, error) @@ -126,6 +127,7 @@ type mockRPCClient struct { abciQuery mockABCIQuery abciInfo mockABCIInfo abciQueryWithOptions mockABCIQueryWithOptions + abciHeight mockABCIHeight broadcastTxAsync mockBroadcastTxAsync broadcastTxSync mockBroadcastTxSync genesis mockGenesis @@ -173,6 +175,13 @@ func (m *mockRPCClient) ABCIQueryWithOptions(path string, data []byte, opts clie return nil, nil } +func (m *mockRPCClient) ABCIHeight(height int64) (*ctypes.ResultABCIQuery, error) { + if m.abciHeight != nil { + return m.abciHeight(height) + } + return nil, nil +} + func (m *mockRPCClient) BroadcastTxAsync(tx types.Tx) (*ctypes.ResultBroadcastTx, error) { if m.broadcastTxAsync != nil { return m.broadcastTxAsync(tx) diff --git a/tm2/pkg/bft/rpc/client/batch.go b/tm2/pkg/bft/rpc/client/batch.go index 9cee83b0f62..0d31044ea33 100644 --- a/tm2/pkg/bft/rpc/client/batch.go +++ b/tm2/pkg/bft/rpc/client/batch.go @@ -161,6 +161,21 @@ func (b *RPCBatch) ABCIQueryWithOptions(path string, data []byte, opts ABCIQuery return nil } +func (b *RPCBatch) ABCIHeight(height int64) error { + // Prepare the RPC request + request, err := newRequest( + abciHeightMethod, + map[string]any{"height": height}, + ) + if err != nil { + return fmt.Errorf("unable to create request, %w", err) + } + + b.addRequest(request, &ctypes.ResultABCIQuery{}) + + return nil +} + func (b *RPCBatch) BroadcastTxCommit(tx types.Tx) error { // Prepare the RPC request request, err := newRequest( diff --git a/tm2/pkg/bft/rpc/client/batch_test.go b/tm2/pkg/bft/rpc/client/batch_test.go index 52930e5c372..42100ceb589 100644 --- a/tm2/pkg/bft/rpc/client/batch_test.go +++ b/tm2/pkg/bft/rpc/client/batch_test.go @@ -208,6 +208,24 @@ func TestRPCBatch_Endpoints(t *testing.T) { return castResult }, }, + { + abciHeightMethod, + &ctypes.ResultABCIQuery{ + Response: abci.ResponseQuery{ + Value: []byte("dummy"), + Height: 10, + }, + }, + func(batch *RPCBatch) { + require.NoError(t, batch.ABCIHeight(10)) + }, + func(result any) any { + castResult, ok := result.(*ctypes.ResultABCIQuery) + require.True(t, ok) + + return castResult + }, + }, { broadcastTxCommitMethod, &ctypes.ResultBroadcastTxCommit{ diff --git a/tm2/pkg/bft/rpc/client/client.go b/tm2/pkg/bft/rpc/client/client.go index e7c7d578ef3..c919384371b 100644 --- a/tm2/pkg/bft/rpc/client/client.go +++ b/tm2/pkg/bft/rpc/client/client.go @@ -22,6 +22,7 @@ const ( statusMethod = "status" abciInfoMethod = "abci_info" abciQueryMethod = "abci_query" + abciHeightMethod = "abci_height" broadcastTxCommitMethod = "broadcast_tx_commit" broadcastTxAsyncMethod = "broadcast_tx_async" broadcastTxSyncMethod = "broadcast_tx_sync" @@ -143,6 +144,15 @@ func (c *RPCClient) ABCIQueryWithOptions(path string, data []byte, opts ABCIQuer ) } +func (c *RPCClient) ABCIHeight(height int64) (*ctypes.ResultABCIQuery, error) { + return sendRequestCommon[ctypes.ResultABCIQuery]( + c.caller, + c.requestTimeout, + abciHeightMethod, + map[string]any{"height": height}, + ) +} + func (c *RPCClient) BroadcastTxCommit(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) { return sendRequestCommon[ctypes.ResultBroadcastTxCommit]( c.caller, diff --git a/tm2/pkg/bft/rpc/client/client_test.go b/tm2/pkg/bft/rpc/client/client_test.go index cb88c91fc5f..9eb581870fa 100644 --- a/tm2/pkg/bft/rpc/client/client_test.go +++ b/tm2/pkg/bft/rpc/client/client_test.go @@ -218,6 +218,43 @@ func TestRPCClient_ABCIQuery(t *testing.T) { assert.Equal(t, expectedQuery, query) } +func TestRPCClient_ABCIHeight(t *testing.T) { + t.Parallel() + + var ( + height = int64(10) + + expectedResult = &ctypes.ResultABCIQuery{ + Response: abci.ResponseQuery{ + Value: []byte("dummy"), + Height: height, + }, + } + + verifyFn = func(t *testing.T, params map[string]any) { + t.Helper() + + assert.Equal(t, fmt.Sprintf("%d", height), params["height"]) + } + + mockClient = generateMockRequestClient( + t, + abciHeightMethod, + verifyFn, + expectedResult, + ) + ) + + c := NewRPCClient(mockClient) + + // Get the query result from given height + result, err := c.ABCIHeight(height) + require.NoError(t, err) + + assert.Equal(t, expectedResult, result) + t.Log(result) +} + func TestRPCClient_BroadcastTxCommit(t *testing.T) { t.Parallel() diff --git a/tm2/pkg/bft/rpc/client/e2e_test.go b/tm2/pkg/bft/rpc/client/e2e_test.go index 08d4b9b735d..d98b9e3770a 100644 --- a/tm2/pkg/bft/rpc/client/e2e_test.go +++ b/tm2/pkg/bft/rpc/client/e2e_test.go @@ -209,6 +209,21 @@ func TestRPCClient_E2E_Endpoints(t *testing.T) { assert.Equal(t, expectedResult, result) }, }, + { + abciHeightMethod, + &ctypes.ResultABCIQuery{ + Response: abci.ResponseQuery{ + Value: []byte("dummy"), + Height: 1000, + }, + }, + func(client *RPCClient, expectedResult any) { + result, err := client.ABCIHeight(1000) + require.NoError(t, err) + + assert.Equal(t, expectedResult, result) + }, + }, { broadcastTxCommitMethod, &ctypes.ResultBroadcastTxCommit{ diff --git a/tm2/pkg/bft/rpc/client/local.go b/tm2/pkg/bft/rpc/client/local.go index 59c4216a468..0a59f67988e 100644 --- a/tm2/pkg/bft/rpc/client/local.go +++ b/tm2/pkg/bft/rpc/client/local.go @@ -66,6 +66,10 @@ func (c *Local) ABCIQueryWithOptions(path string, data []byte, opts ABCIQueryOpt return core.ABCIQuery(c.ctx, path, data, opts.Height, opts.Prove) } +func (c *Local) ABCIHeight(height int64) (*ctypes.ResultABCIQuery, error) { + return core.ABCIHeight(c.ctx, height) +} + func (c *Local) BroadcastTxCommit(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) { return core.BroadcastTxCommit(c.ctx, tx) } diff --git a/tm2/pkg/bft/rpc/client/types.go b/tm2/pkg/bft/rpc/client/types.go index 52427a1a818..8b9cca39391 100644 --- a/tm2/pkg/bft/rpc/client/types.go +++ b/tm2/pkg/bft/rpc/client/types.go @@ -42,7 +42,7 @@ type ABCIClient interface { ABCIQuery(path string, data []byte) (*ctypes.ResultABCIQuery, error) ABCIQueryWithOptions(path string, data []byte, opts ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) - + ABCIHeight(height int64) (*ctypes.ResultABCIQuery, error) // Writing to abci app BroadcastTxCommit(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) BroadcastTxAsync(tx types.Tx) (*ctypes.ResultBroadcastTx, error) diff --git a/tm2/pkg/bft/rpc/core/abci.go b/tm2/pkg/bft/rpc/core/abci.go index aef90052f58..c392c42c765 100644 --- a/tm2/pkg/bft/rpc/core/abci.go +++ b/tm2/pkg/bft/rpc/core/abci.go @@ -1,6 +1,8 @@ package core import ( + "fmt" + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" rpctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/lib/types" @@ -69,6 +71,63 @@ func ABCIQuery(ctx *rpctypes.Context, path string, data []byte, height int64, pr return &ctypes.ResultABCIQuery{Response: resQuery}, nil } +// Query at a specific block height. +// +// ```shell +// curl 'localhost:26657/abci_height?height=100' +// ``` +// +// ```go +// client := client.NewHTTP("tcp://0.0.0.0:26657", "/websocket") +// +// err := client.Start() +// +// if err != nil { +// // handle error +// } +// +// defer client.Stop() +// result, err := client.ABCIHeight(100) +// ``` +// +// > The above command returns JSON structured like this: +// +// ```json +// +// { +// "error": "", +// "result": { +// "response": { +// "log": "exists", +// "height": "100", +// // ... +// } +// }, +// "id": "", +// "jsonrpc": "2.0" +// } +// +// ``` +// +// ### Query Parameter +// +// - height (int64): The height to query at. +func ABCIHeight(ctx *rpctypes.Context, height int64) (*ctypes.ResultABCIQuery, error) { + if height <= 0 { + return nil, fmt.Errorf("height must be greater than 0") + } + + resQuery, err := proxyAppQuery.QuerySync(abci.RequestQuery{ + Height: height, + }) + if err != nil { + return nil, err + } + + logger.Info("ABCIAtHeight", "height", height, "result", resQuery) + return &ctypes.ResultABCIQuery{Response: resQuery}, nil +} + // Get some info about the application. // // ```shell diff --git a/tm2/pkg/bft/rpc/core/routes.go b/tm2/pkg/bft/rpc/core/routes.go index 8d210f67985..202e6feb7eb 100644 --- a/tm2/pkg/bft/rpc/core/routes.go +++ b/tm2/pkg/bft/rpc/core/routes.go @@ -30,8 +30,9 @@ var Routes = map[string]*rpc.RPCFunc{ "broadcast_tx_async": rpc.NewRPCFunc(BroadcastTxAsync, "tx"), // abci API - "abci_query": rpc.NewRPCFunc(ABCIQuery, "path,data,height,prove"), - "abci_info": rpc.NewRPCFunc(ABCIInfo, ""), + "abci_query": rpc.NewRPCFunc(ABCIQuery, "path,data,height,prove"), + "abci_info": rpc.NewRPCFunc(ABCIInfo, ""), + "abci_height": rpc.NewRPCFunc(ABCIHeight, "height"), } func AddUnsafeRoutes() { From 265bdaf9283b430f18f6820908f44bae3843ef54 Mon Sep 17 00:00:00 2001 From: Lee ByeongJun Date: Thu, 22 Aug 2024 14:12:48 +0900 Subject: [PATCH 2/5] revert --- gno.land/pkg/gnoclient/mock_test.go | 9 ---- tm2/pkg/bft/rpc/client/batch.go | 15 ------- tm2/pkg/bft/rpc/client/batch_test.go | 18 -------- tm2/pkg/bft/rpc/client/client.go | 10 ----- tm2/pkg/bft/rpc/client/client_test.go | 37 ----------------- tm2/pkg/bft/rpc/client/e2e_test.go | 15 ------- tm2/pkg/bft/rpc/client/local.go | 4 -- tm2/pkg/bft/rpc/client/types.go | 1 - tm2/pkg/bft/rpc/core/abci.go | 59 --------------------------- tm2/pkg/bft/rpc/core/routes.go | 1 - 10 files changed, 169 deletions(-) diff --git a/gno.land/pkg/gnoclient/mock_test.go b/gno.land/pkg/gnoclient/mock_test.go index 87a97b30d33..64da62936c2 100644 --- a/gno.land/pkg/gnoclient/mock_test.go +++ b/gno.land/pkg/gnoclient/mock_test.go @@ -102,7 +102,6 @@ type ( mockABCIQuery func(path string, data []byte) (*ctypes.ResultABCIQuery, error) mockABCIInfo func() (*ctypes.ResultABCIInfo, error) mockABCIQueryWithOptions func(path string, data []byte, opts client.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) - mockABCIHeight func(height int64) (*ctypes.ResultABCIQuery, error) mockBroadcastTxAsync func(tx types.Tx) (*ctypes.ResultBroadcastTx, error) mockBroadcastTxSync func(tx types.Tx) (*ctypes.ResultBroadcastTx, error) mockGenesis func() (*ctypes.ResultGenesis, error) @@ -127,7 +126,6 @@ type mockRPCClient struct { abciQuery mockABCIQuery abciInfo mockABCIInfo abciQueryWithOptions mockABCIQueryWithOptions - abciHeight mockABCIHeight broadcastTxAsync mockBroadcastTxAsync broadcastTxSync mockBroadcastTxSync genesis mockGenesis @@ -175,13 +173,6 @@ func (m *mockRPCClient) ABCIQueryWithOptions(path string, data []byte, opts clie return nil, nil } -func (m *mockRPCClient) ABCIHeight(height int64) (*ctypes.ResultABCIQuery, error) { - if m.abciHeight != nil { - return m.abciHeight(height) - } - return nil, nil -} - func (m *mockRPCClient) BroadcastTxAsync(tx types.Tx) (*ctypes.ResultBroadcastTx, error) { if m.broadcastTxAsync != nil { return m.broadcastTxAsync(tx) diff --git a/tm2/pkg/bft/rpc/client/batch.go b/tm2/pkg/bft/rpc/client/batch.go index 0d31044ea33..9cee83b0f62 100644 --- a/tm2/pkg/bft/rpc/client/batch.go +++ b/tm2/pkg/bft/rpc/client/batch.go @@ -161,21 +161,6 @@ func (b *RPCBatch) ABCIQueryWithOptions(path string, data []byte, opts ABCIQuery return nil } -func (b *RPCBatch) ABCIHeight(height int64) error { - // Prepare the RPC request - request, err := newRequest( - abciHeightMethod, - map[string]any{"height": height}, - ) - if err != nil { - return fmt.Errorf("unable to create request, %w", err) - } - - b.addRequest(request, &ctypes.ResultABCIQuery{}) - - return nil -} - func (b *RPCBatch) BroadcastTxCommit(tx types.Tx) error { // Prepare the RPC request request, err := newRequest( diff --git a/tm2/pkg/bft/rpc/client/batch_test.go b/tm2/pkg/bft/rpc/client/batch_test.go index 42100ceb589..52930e5c372 100644 --- a/tm2/pkg/bft/rpc/client/batch_test.go +++ b/tm2/pkg/bft/rpc/client/batch_test.go @@ -208,24 +208,6 @@ func TestRPCBatch_Endpoints(t *testing.T) { return castResult }, }, - { - abciHeightMethod, - &ctypes.ResultABCIQuery{ - Response: abci.ResponseQuery{ - Value: []byte("dummy"), - Height: 10, - }, - }, - func(batch *RPCBatch) { - require.NoError(t, batch.ABCIHeight(10)) - }, - func(result any) any { - castResult, ok := result.(*ctypes.ResultABCIQuery) - require.True(t, ok) - - return castResult - }, - }, { broadcastTxCommitMethod, &ctypes.ResultBroadcastTxCommit{ diff --git a/tm2/pkg/bft/rpc/client/client.go b/tm2/pkg/bft/rpc/client/client.go index c919384371b..e7c7d578ef3 100644 --- a/tm2/pkg/bft/rpc/client/client.go +++ b/tm2/pkg/bft/rpc/client/client.go @@ -22,7 +22,6 @@ const ( statusMethod = "status" abciInfoMethod = "abci_info" abciQueryMethod = "abci_query" - abciHeightMethod = "abci_height" broadcastTxCommitMethod = "broadcast_tx_commit" broadcastTxAsyncMethod = "broadcast_tx_async" broadcastTxSyncMethod = "broadcast_tx_sync" @@ -144,15 +143,6 @@ func (c *RPCClient) ABCIQueryWithOptions(path string, data []byte, opts ABCIQuer ) } -func (c *RPCClient) ABCIHeight(height int64) (*ctypes.ResultABCIQuery, error) { - return sendRequestCommon[ctypes.ResultABCIQuery]( - c.caller, - c.requestTimeout, - abciHeightMethod, - map[string]any{"height": height}, - ) -} - func (c *RPCClient) BroadcastTxCommit(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) { return sendRequestCommon[ctypes.ResultBroadcastTxCommit]( c.caller, diff --git a/tm2/pkg/bft/rpc/client/client_test.go b/tm2/pkg/bft/rpc/client/client_test.go index 9eb581870fa..cb88c91fc5f 100644 --- a/tm2/pkg/bft/rpc/client/client_test.go +++ b/tm2/pkg/bft/rpc/client/client_test.go @@ -218,43 +218,6 @@ func TestRPCClient_ABCIQuery(t *testing.T) { assert.Equal(t, expectedQuery, query) } -func TestRPCClient_ABCIHeight(t *testing.T) { - t.Parallel() - - var ( - height = int64(10) - - expectedResult = &ctypes.ResultABCIQuery{ - Response: abci.ResponseQuery{ - Value: []byte("dummy"), - Height: height, - }, - } - - verifyFn = func(t *testing.T, params map[string]any) { - t.Helper() - - assert.Equal(t, fmt.Sprintf("%d", height), params["height"]) - } - - mockClient = generateMockRequestClient( - t, - abciHeightMethod, - verifyFn, - expectedResult, - ) - ) - - c := NewRPCClient(mockClient) - - // Get the query result from given height - result, err := c.ABCIHeight(height) - require.NoError(t, err) - - assert.Equal(t, expectedResult, result) - t.Log(result) -} - func TestRPCClient_BroadcastTxCommit(t *testing.T) { t.Parallel() diff --git a/tm2/pkg/bft/rpc/client/e2e_test.go b/tm2/pkg/bft/rpc/client/e2e_test.go index d98b9e3770a..08d4b9b735d 100644 --- a/tm2/pkg/bft/rpc/client/e2e_test.go +++ b/tm2/pkg/bft/rpc/client/e2e_test.go @@ -209,21 +209,6 @@ func TestRPCClient_E2E_Endpoints(t *testing.T) { assert.Equal(t, expectedResult, result) }, }, - { - abciHeightMethod, - &ctypes.ResultABCIQuery{ - Response: abci.ResponseQuery{ - Value: []byte("dummy"), - Height: 1000, - }, - }, - func(client *RPCClient, expectedResult any) { - result, err := client.ABCIHeight(1000) - require.NoError(t, err) - - assert.Equal(t, expectedResult, result) - }, - }, { broadcastTxCommitMethod, &ctypes.ResultBroadcastTxCommit{ diff --git a/tm2/pkg/bft/rpc/client/local.go b/tm2/pkg/bft/rpc/client/local.go index 0a59f67988e..59c4216a468 100644 --- a/tm2/pkg/bft/rpc/client/local.go +++ b/tm2/pkg/bft/rpc/client/local.go @@ -66,10 +66,6 @@ func (c *Local) ABCIQueryWithOptions(path string, data []byte, opts ABCIQueryOpt return core.ABCIQuery(c.ctx, path, data, opts.Height, opts.Prove) } -func (c *Local) ABCIHeight(height int64) (*ctypes.ResultABCIQuery, error) { - return core.ABCIHeight(c.ctx, height) -} - func (c *Local) BroadcastTxCommit(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) { return core.BroadcastTxCommit(c.ctx, tx) } diff --git a/tm2/pkg/bft/rpc/client/types.go b/tm2/pkg/bft/rpc/client/types.go index 8b9cca39391..90ed52c243c 100644 --- a/tm2/pkg/bft/rpc/client/types.go +++ b/tm2/pkg/bft/rpc/client/types.go @@ -42,7 +42,6 @@ type ABCIClient interface { ABCIQuery(path string, data []byte) (*ctypes.ResultABCIQuery, error) ABCIQueryWithOptions(path string, data []byte, opts ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) - ABCIHeight(height int64) (*ctypes.ResultABCIQuery, error) // Writing to abci app BroadcastTxCommit(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) BroadcastTxAsync(tx types.Tx) (*ctypes.ResultBroadcastTx, error) diff --git a/tm2/pkg/bft/rpc/core/abci.go b/tm2/pkg/bft/rpc/core/abci.go index c392c42c765..aef90052f58 100644 --- a/tm2/pkg/bft/rpc/core/abci.go +++ b/tm2/pkg/bft/rpc/core/abci.go @@ -1,8 +1,6 @@ package core import ( - "fmt" - abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" rpctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/lib/types" @@ -71,63 +69,6 @@ func ABCIQuery(ctx *rpctypes.Context, path string, data []byte, height int64, pr return &ctypes.ResultABCIQuery{Response: resQuery}, nil } -// Query at a specific block height. -// -// ```shell -// curl 'localhost:26657/abci_height?height=100' -// ``` -// -// ```go -// client := client.NewHTTP("tcp://0.0.0.0:26657", "/websocket") -// -// err := client.Start() -// -// if err != nil { -// // handle error -// } -// -// defer client.Stop() -// result, err := client.ABCIHeight(100) -// ``` -// -// > The above command returns JSON structured like this: -// -// ```json -// -// { -// "error": "", -// "result": { -// "response": { -// "log": "exists", -// "height": "100", -// // ... -// } -// }, -// "id": "", -// "jsonrpc": "2.0" -// } -// -// ``` -// -// ### Query Parameter -// -// - height (int64): The height to query at. -func ABCIHeight(ctx *rpctypes.Context, height int64) (*ctypes.ResultABCIQuery, error) { - if height <= 0 { - return nil, fmt.Errorf("height must be greater than 0") - } - - resQuery, err := proxyAppQuery.QuerySync(abci.RequestQuery{ - Height: height, - }) - if err != nil { - return nil, err - } - - logger.Info("ABCIAtHeight", "height", height, "result", resQuery) - return &ctypes.ResultABCIQuery{Response: resQuery}, nil -} - // Get some info about the application. // // ```shell diff --git a/tm2/pkg/bft/rpc/core/routes.go b/tm2/pkg/bft/rpc/core/routes.go index 202e6feb7eb..010fbf1d5f7 100644 --- a/tm2/pkg/bft/rpc/core/routes.go +++ b/tm2/pkg/bft/rpc/core/routes.go @@ -32,7 +32,6 @@ var Routes = map[string]*rpc.RPCFunc{ // abci API "abci_query": rpc.NewRPCFunc(ABCIQuery, "path,data,height,prove"), "abci_info": rpc.NewRPCFunc(ABCIInfo, ""), - "abci_height": rpc.NewRPCFunc(ABCIHeight, "height"), } func AddUnsafeRoutes() { From 2fae41e3d502aa2d8e10d675932c7f6ddef50716 Mon Sep 17 00:00:00 2001 From: Lee ByeongJun Date: Fri, 23 Aug 2024 11:28:18 +0900 Subject: [PATCH 3/5] fix --- tm2/pkg/bft/rpc/client/batch.go | 18 ++++++------- tm2/pkg/bft/rpc/client/batch_test.go | 18 +++++++++++++ tm2/pkg/bft/rpc/client/client.go | 2 +- tm2/pkg/bft/rpc/client/e2e_test.go | 16 ++++++++++++ tm2/pkg/bft/rpc/core/abci.go | 21 ++++++++++++--- tm2/pkg/bft/rpc/core/routes.go | 4 +-- tm2/pkg/crypto/keys/client/query.go | 27 +++++++++++++++++--- tm2/pkg/sdk/baseapp.go | 38 +++++++++++++++++++++++----- 8 files changed, 117 insertions(+), 27 deletions(-) diff --git a/tm2/pkg/bft/rpc/client/batch.go b/tm2/pkg/bft/rpc/client/batch.go index 9cee83b0f62..7a64242b7d4 100644 --- a/tm2/pkg/bft/rpc/client/batch.go +++ b/tm2/pkg/bft/rpc/client/batch.go @@ -142,16 +142,16 @@ func (b *RPCBatch) ABCIQuery(path string, data []byte) error { } func (b *RPCBatch) ABCIQueryWithOptions(path string, data []byte, opts ABCIQueryOptions) error { + params := map[string]any{ + "path": path, + "data": data, + "prove": opts.Prove, + } + if opts.Height != 0 { + params["height"] = opts.Height + } // Prepare the RPC request - request, err := newRequest( - abciQueryMethod, - map[string]any{ - "path": path, - "data": data, - "height": opts.Height, - "prove": opts.Prove, - }, - ) + request, err := newRequest(abciQueryMethod, params) if err != nil { return fmt.Errorf("unable to create request, %w", err) } diff --git a/tm2/pkg/bft/rpc/client/batch_test.go b/tm2/pkg/bft/rpc/client/batch_test.go index 52930e5c372..ef3b5c8087b 100644 --- a/tm2/pkg/bft/rpc/client/batch_test.go +++ b/tm2/pkg/bft/rpc/client/batch_test.go @@ -208,6 +208,24 @@ func TestRPCBatch_Endpoints(t *testing.T) { return castResult }, }, + { + abciQueryMethod, + &ctypes.ResultABCIQuery{ + Response: abci.ResponseQuery{ + Value: []byte("dummy"), + Height: 10, + }, + }, + func(batch *RPCBatch) { + require.NoError(t, batch.ABCIQueryWithOptions("path", []byte("dummy"), ABCIQueryOptions{Height: 10, Prove: false})) + }, + func(result any) any { + castResult, ok := result.(*ctypes.ResultABCIQuery) + require.True(t, ok) + assert.Equal(t, int64(10), castResult.Response.Height) + return castResult + }, + }, { broadcastTxCommitMethod, &ctypes.ResultBroadcastTxCommit{ diff --git a/tm2/pkg/bft/rpc/client/client.go b/tm2/pkg/bft/rpc/client/client.go index e7c7d578ef3..68681cc702f 100644 --- a/tm2/pkg/bft/rpc/client/client.go +++ b/tm2/pkg/bft/rpc/client/client.go @@ -137,8 +137,8 @@ func (c *RPCClient) ABCIQueryWithOptions(path string, data []byte, opts ABCIQuer map[string]any{ "path": path, "data": data, - "height": opts.Height, "prove": opts.Prove, + "height": opts.Height, }, ) } diff --git a/tm2/pkg/bft/rpc/client/e2e_test.go b/tm2/pkg/bft/rpc/client/e2e_test.go index 08d4b9b735d..300beea6833 100644 --- a/tm2/pkg/bft/rpc/client/e2e_test.go +++ b/tm2/pkg/bft/rpc/client/e2e_test.go @@ -209,6 +209,22 @@ func TestRPCClient_E2E_Endpoints(t *testing.T) { assert.Equal(t, expectedResult, result) }, }, + { + abciQueryMethod, + &ctypes.ResultABCIQuery{ + Response: abci.ResponseQuery{ + Value: []byte("dummy"), + Height: 10, + }, + }, + func(client *RPCClient, expectedResult any) { + result, err := client.ABCIQueryWithOptions("path", []byte("dummy"), ABCIQueryOptions{Height: 10, Prove: false}) + require.NoError(t, err) + + assert.Equal(t, expectedResult, result) + assert.Equal(t, int64(10), result.Response.Height) + }, + }, { broadcastTxCommitMethod, &ctypes.ResultBroadcastTxCommit{ diff --git a/tm2/pkg/bft/rpc/core/abci.go b/tm2/pkg/bft/rpc/core/abci.go index aef90052f58..ff2a90bc555 100644 --- a/tm2/pkg/bft/rpc/core/abci.go +++ b/tm2/pkg/bft/rpc/core/abci.go @@ -1,15 +1,19 @@ package core import ( + "errors" + "fmt" + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" rpctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/lib/types" ) -// Query the application for some information. +// Query the application for some information. It allows querying the +// application's state at a specific height. // // ```shell -// curl 'localhost:26657/abci_query?path=""&data="abcd"&prove=false' +// curl 'localhost:26657/abci_query?path=""&data="abcd"&height=10&prove=false' // ``` // // ```go @@ -21,7 +25,7 @@ import ( // } // // defer client.Stop() -// result, err := client.ABCIQuery("", "abcd", true) +// result, err := client.ABCIQuery("", "abcd", 10, true) // ``` // // > The above command returns JSON structured like this: @@ -33,7 +37,7 @@ import ( // "result": { // "response": { // "log": "exists", -// "height": "0", +// "height": "10", // "proof": "010114FED0DAD959F36091AD761C922ABA3CBF1D8349990101020103011406AA2262E2F448242DF2C2607C3CDC705313EE3B0001149D16177BC71E445476174622EA559715C293740C", // "value": "61626364", // "key": "61626364", @@ -56,6 +60,15 @@ import ( // | height | int64 | 0 | false | Height (0 means latest) | // | prove | bool | false | false | Includes proof if true | func ABCIQuery(ctx *rpctypes.Context, path string, data []byte, height int64, prove bool) (*ctypes.ResultABCIQuery, error) { + if height < 0 { + return nil, errors.New("height cannot be negative") + } + currentHeight := blockStore.Height() + + if height > currentHeight { + return nil, fmt.Errorf("requested height %d is in the future (latest height is %d)", height, currentHeight) + } + resQuery, err := proxyAppQuery.QuerySync(abci.RequestQuery{ Path: path, Data: data, diff --git a/tm2/pkg/bft/rpc/core/routes.go b/tm2/pkg/bft/rpc/core/routes.go index 010fbf1d5f7..8d210f67985 100644 --- a/tm2/pkg/bft/rpc/core/routes.go +++ b/tm2/pkg/bft/rpc/core/routes.go @@ -30,8 +30,8 @@ var Routes = map[string]*rpc.RPCFunc{ "broadcast_tx_async": rpc.NewRPCFunc(BroadcastTxAsync, "tx"), // abci API - "abci_query": rpc.NewRPCFunc(ABCIQuery, "path,data,height,prove"), - "abci_info": rpc.NewRPCFunc(ABCIInfo, ""), + "abci_query": rpc.NewRPCFunc(ABCIQuery, "path,data,height,prove"), + "abci_info": rpc.NewRPCFunc(ABCIInfo, ""), } func AddUnsafeRoutes() { diff --git a/tm2/pkg/crypto/keys/client/query.go b/tm2/pkg/crypto/keys/client/query.go index 3278d0ea0ea..e274aa42a4f 100644 --- a/tm2/pkg/crypto/keys/client/query.go +++ b/tm2/pkg/crypto/keys/client/query.go @@ -13,8 +13,10 @@ import ( type QueryCfg struct { RootCfg *BaseCfg - Data string - Path string + Data string + Path string + Height int64 + Prove bool } func NewQueryCmd(rootCfg *BaseCfg, io commands.IO) *commands.Command { @@ -42,6 +44,18 @@ func (c *QueryCfg) RegisterFlags(fs *flag.FlagSet) { "", "query data bytes", ) + fs.Int64Var( + &c.Height, + "height", + 0, + "height to query (0 means latest)", + ) + fs.BoolVar( + &c.Prove, + "prove", + false, + "include proofs of the transactions inclusion in the block", + ) } func execQuery(cfg *QueryCfg, args []string, io commands.IO) error { @@ -69,6 +83,11 @@ func execQuery(cfg *QueryCfg, args []string, io commands.IO) error { io.Printf("height: %d\ndata: %s\n", height, string(resdata)) + if cfg.Prove { + io.Printf("proof: %x\n", + qres.Response.Proof, + ) + } return nil } @@ -80,8 +99,8 @@ func QueryHandler(cfg *QueryCfg) (*ctypes.ResultABCIQuery, error) { data := []byte(cfg.Data) opts2 := client.ABCIQueryOptions{ - // Height: height, XXX - // Prove: false, XXX + Height: cfg.Height, + Prove: cfg.Prove, } cli, err := client.NewHTTPClient(remote) if err != nil { diff --git a/tm2/pkg/sdk/baseapp.go b/tm2/pkg/sdk/baseapp.go index 0fa26b817e1..2277615062b 100644 --- a/tm2/pkg/sdk/baseapp.go +++ b/tm2/pkg/sdk/baseapp.go @@ -49,6 +49,7 @@ type BaseApp struct { // See methods setCheckState and setDeliverState. checkState *state // for CheckTx deliverState *state // for DeliverTx + currentState *state // current state, set after Commit voteInfos []abci.VoteInfo // absent validators from begin block // consensus params @@ -240,6 +241,7 @@ func (app *BaseApp) setCheckState(header abci.Header) { ms: ms, ctx: NewContext(RunTxModeCheck, ms, header, app.logger).WithMinGasPrices(app.minGasPrices), } + app.currentState = nil // reset the current state } // setDeliverState sets deliverState with the cached multistore and @@ -252,6 +254,7 @@ func (app *BaseApp) setDeliverState(header abci.Header) { ms: ms, ctx: NewContext(RunTxModeDeliver, ms, header, app.logger), } + app.currentState = nil // reset the current state } // setConsensusParams memoizes the consensus params. @@ -389,10 +392,6 @@ func (app *BaseApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) { default: return handleQueryCustom(app, path, req) } - - msg := "unknown query path " + req.Path - res.Error = ABCIError(std.ErrUnknownRequest(msg)) - return } func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) (res abci.ResponseQuery) { @@ -474,6 +473,8 @@ func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res return } + state := app.CurrentState() + cacheMS, err := app.cms.MultiImmutableCacheWrapWithVersion(req.Height) if err != nil { res.Error = ABCIError(std.ErrInternal( @@ -487,7 +488,11 @@ func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res // cache wrap the commit-multistore for safety // XXX RunTxModeQuery? - ctx := NewContext(RunTxModeCheck, cacheMS, app.checkState.ctx.BlockHeader(), app.logger).WithMinGasPrices(app.minGasPrices) + // ctx := NewContext(RunTxModeCheck, cacheMS, app.checkState.ctx.BlockHeader(), app.logger).WithMinGasPrices(app.minGasPrices) + ctx := state.ctx. + WithMultiStore(cacheMS). + WithMode(RunTxModeCheck). + WithMinGasPrices(app.minGasPrices) // Passes the query to the handler. res = handler.Query(ctx, req) @@ -898,6 +903,9 @@ func (app *BaseApp) Commit() (res abci.ResponseCommit) { // empty/reset the deliver state app.deliverState = nil + // Reset current state + app.currentState = nil + // return. res.Data = commitID.Hash return @@ -933,9 +941,10 @@ func (app *BaseApp) Close() error { // ---------------------------------------------------------------------------- // State +// state represents the application state at a given point. type state struct { - ms store.MultiStore - ctx Context + ms store.MultiStore // The multi-store containing the application state + ctx Context // The context associated with the state } func (st *state) MultiCacheWrap() store.MultiStore { @@ -945,3 +954,18 @@ func (st *state) MultiCacheWrap() store.MultiStore { func (st *state) Context() Context { return st.ctx } + +// CurrentState returns the current state of the application. +// It returns the deliver state if it exists, otherwise it returns the check state. +func (app *BaseApp) CurrentState() state { + if app.deliverState != nil { + return state{ + ms: app.deliverState.ms, + ctx: app.checkState.ctx, + } + } + return state{ + ms: app.checkState.ms, + ctx: app.checkState.ctx, + } +} From d1ff7cec8fc9fdcb301d3709582772007c53a480 Mon Sep 17 00:00:00 2001 From: Lee ByeongJun Date: Thu, 19 Sep 2024 14:34:44 +0900 Subject: [PATCH 4/5] test --- tm2/pkg/bft/rpc/core/abci.go | 5 +- tm2/pkg/bft/rpc/core/abci_test.go | 101 ++++++++++++++++++++++++++++++ tm2/pkg/bft/rpc/core/mock_test.go | 28 ++++++++- tm2/pkg/sdk/baseapp.go | 7 --- 4 files changed, 130 insertions(+), 11 deletions(-) create mode 100644 tm2/pkg/bft/rpc/core/abci_test.go diff --git a/tm2/pkg/bft/rpc/core/abci.go b/tm2/pkg/bft/rpc/core/abci.go index ff2a90bc555..db0fb12dfad 100644 --- a/tm2/pkg/bft/rpc/core/abci.go +++ b/tm2/pkg/bft/rpc/core/abci.go @@ -1,7 +1,6 @@ package core import ( - "errors" "fmt" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" @@ -61,7 +60,7 @@ import ( // | prove | bool | false | false | Includes proof if true | func ABCIQuery(ctx *rpctypes.Context, path string, data []byte, height int64, prove bool) (*ctypes.ResultABCIQuery, error) { if height < 0 { - return nil, errors.New("height cannot be negative") + return nil, fmt.Errorf("height cannot be negative: %d", height) } currentHeight := blockStore.Height() @@ -78,7 +77,7 @@ func ABCIQuery(ctx *rpctypes.Context, path string, data []byte, height int64, pr if err != nil { return nil, err } - logger.Info("ABCIQuery", "path", path, "data", data, "result", resQuery) + return &ctypes.ResultABCIQuery{Response: resQuery}, nil } diff --git a/tm2/pkg/bft/rpc/core/abci_test.go b/tm2/pkg/bft/rpc/core/abci_test.go new file mode 100644 index 00000000000..8460af8f0b7 --- /dev/null +++ b/tm2/pkg/bft/rpc/core/abci_test.go @@ -0,0 +1,101 @@ +package core + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" + rpctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/lib/types" +) + +func TestABCIQuery(t *testing.T) { + t.Parallel() + + origBlockStore, origProxyAppQuery := blockStore, proxyAppQuery + defer func() { + blockStore, proxyAppQuery = origBlockStore, origProxyAppQuery + }() + + tests := []struct { + name string + path string + data []byte + height int64 + prove bool + mockHeight int64 + mockQueryResp *abci.ResponseQuery + mockQueryErr error + expectedResult *ctypes.ResultABCIQuery + expectedError string + }{ + { + name: "valid query", + path: "/a/b/c", + data: []byte("data"), + height: 10, + prove: false, + mockHeight: 20, + mockQueryResp: &abci.ResponseQuery{ + Key: []byte("key"), + Value: []byte("result"), + Height: 10, + }, + expectedResult: &ctypes.ResultABCIQuery{ + Response: abci.ResponseQuery{ + Key: []byte("key"), + Value: []byte("result"), + Height: 10, + }, + }, + }, + { + name: "negative height", + height: -1, + mockHeight: 20, + expectedResult: nil, + expectedError: "height cannot be negative", + }, + { + name: "future height", + height: 30, + mockHeight: 20, + expectedResult: nil, + expectedError: "requested height 30 is in the future (latest height is 20)", + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + mockBS := &mockBlockStore{ + heightFn: func() int64 { return tt.mockHeight }, + } + blockStore = mockBS + + mockPAQ := &mockProxyAppQuery{ + queryFn: func(req abci.RequestQuery) (abci.ResponseQuery, error) { + if tt.mockQueryResp != nil { + return *tt.mockQueryResp, tt.mockQueryErr + } + return abci.ResponseQuery{}, tt.mockQueryErr + }, + } + proxyAppQuery = mockPAQ + + result, err := ABCIQuery(&rpctypes.Context{}, tt.path, tt.data, tt.height, tt.prove) + + if tt.expectedError != "" { + assert.Error(t, err) + assert.Contains(t, err.Error(), tt.expectedError) + assert.Nil(t, result) + } else { + assert.NoError(t, err) + assert.Equal(t, tt.expectedResult, result) + } + }) + } +} diff --git a/tm2/pkg/bft/rpc/core/mock_test.go b/tm2/pkg/bft/rpc/core/mock_test.go index a6ffe948d00..67c4d90568a 100644 --- a/tm2/pkg/bft/rpc/core/mock_test.go +++ b/tm2/pkg/bft/rpc/core/mock_test.go @@ -1,6 +1,9 @@ package core -import "github.com/gnolang/gno/tm2/pkg/bft/types" +import ( + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + "github.com/gnolang/gno/tm2/pkg/bft/types" +) type ( heightDelegate func() int64 @@ -76,3 +79,26 @@ func (m *mockBlockStore) SaveBlock(block *types.Block, blockParts *types.PartSet m.saveBlockFn(block, blockParts, seenCommit) } } + +type mockProxyAppQuery struct { + queryFn func(req abci.RequestQuery) (abci.ResponseQuery, error) +} + +func (m *mockProxyAppQuery) QuerySync(req abci.RequestQuery) (abci.ResponseQuery, error) { + if m.queryFn != nil { + return m.queryFn(req) + } + return abci.ResponseQuery{}, nil +} + +func (m *mockProxyAppQuery) EchoSync(msg string) (abci.ResponseEcho, error) { + return abci.ResponseEcho{}, nil +} + +func (m *mockProxyAppQuery) InfoSync(req abci.RequestInfo) (abci.ResponseInfo, error) { + return abci.ResponseInfo{}, nil +} + +func (m *mockProxyAppQuery) Error() error { + return nil +} diff --git a/tm2/pkg/sdk/baseapp.go b/tm2/pkg/sdk/baseapp.go index 2277615062b..cfa86672aa2 100644 --- a/tm2/pkg/sdk/baseapp.go +++ b/tm2/pkg/sdk/baseapp.go @@ -49,7 +49,6 @@ type BaseApp struct { // See methods setCheckState and setDeliverState. checkState *state // for CheckTx deliverState *state // for DeliverTx - currentState *state // current state, set after Commit voteInfos []abci.VoteInfo // absent validators from begin block // consensus params @@ -241,7 +240,6 @@ func (app *BaseApp) setCheckState(header abci.Header) { ms: ms, ctx: NewContext(RunTxModeCheck, ms, header, app.logger).WithMinGasPrices(app.minGasPrices), } - app.currentState = nil // reset the current state } // setDeliverState sets deliverState with the cached multistore and @@ -254,7 +252,6 @@ func (app *BaseApp) setDeliverState(header abci.Header) { ms: ms, ctx: NewContext(RunTxModeDeliver, ms, header, app.logger), } - app.currentState = nil // reset the current state } // setConsensusParams memoizes the consensus params. @@ -488,7 +485,6 @@ func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res // cache wrap the commit-multistore for safety // XXX RunTxModeQuery? - // ctx := NewContext(RunTxModeCheck, cacheMS, app.checkState.ctx.BlockHeader(), app.logger).WithMinGasPrices(app.minGasPrices) ctx := state.ctx. WithMultiStore(cacheMS). WithMode(RunTxModeCheck). @@ -903,9 +899,6 @@ func (app *BaseApp) Commit() (res abci.ResponseCommit) { // empty/reset the deliver state app.deliverState = nil - // Reset current state - app.currentState = nil - // return. res.Data = commitID.Hash return From 9afbe23e68283133af6f4aed422585b366ee7f7a Mon Sep 17 00:00:00 2001 From: Lee ByeongJun Date: Thu, 19 Sep 2024 14:52:34 +0900 Subject: [PATCH 5/5] fix --- tm2/pkg/bft/rpc/client/batch.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tm2/pkg/bft/rpc/client/batch.go b/tm2/pkg/bft/rpc/client/batch.go index 7a64242b7d4..13eb1a4b067 100644 --- a/tm2/pkg/bft/rpc/client/batch.go +++ b/tm2/pkg/bft/rpc/client/batch.go @@ -147,7 +147,7 @@ func (b *RPCBatch) ABCIQueryWithOptions(path string, data []byte, opts ABCIQuery "data": data, "prove": opts.Prove, } - if opts.Height != 0 { + if opts.Height > 0 { params["height"] = opts.Height } // Prepare the RPC request