Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add 'raw' query parameter to the blocks #899

Merged
merged 6 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions api/blocks/blocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
package blocks

import (
"encoding/hex"
"fmt"
"net/http"

"github.com/ethereum/go-ethereum/rlp"
"github.com/gorilla/mux"
"github.com/pkg/errors"
"github.com/vechain/thor/v2/api/utils"
Expand All @@ -34,9 +37,17 @@ func (b *Blocks) handleGetBlock(w http.ResponseWriter, req *http.Request) error
if err != nil {
return utils.BadRequest(errors.WithMessage(err, "revision"))
}
expanded := req.URL.Query().Get("expanded")
if expanded != "" && expanded != "false" && expanded != "true" {
return utils.BadRequest(errors.WithMessage(errors.New("should be boolean"), "expanded"))
raw, err := utils.StringToBoolean(req.URL.Query().Get("raw"), false)
if err != nil {
return utils.BadRequest(errors.WithMessage(err, "raw"))
}
expanded, err := utils.StringToBoolean(req.URL.Query().Get("expanded"), false)
if err != nil {
return utils.BadRequest(errors.WithMessage(err, "expanded"))
}

if raw && expanded {
return utils.BadRequest(errors.WithMessage(errors.New("Raw and Expanded are mutually exclusive"), "raw&expanded"))
}

summary, err := utils.GetSummary(revision, b.repo, b.bft)
Expand All @@ -47,6 +58,16 @@ func (b *Blocks) handleGetBlock(w http.ResponseWriter, req *http.Request) error
return err
}

if raw {
rlpEncoded, err := rlp.EncodeToBytes(summary.Header)
if err != nil {
return err
}
return utils.WriteJSON(w, &JSONRawBlockSummary{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we create a unit test to make the API call and decode the response body?

Copy link
Contributor

@leszek-vechain leszek-vechain Nov 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was going to ask about tests - I suppose we need to update e2e tests for it ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think so and also internal unit tests in thor

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fmt.Sprintf("0x%s", hex.EncodeToString(rlpEncoded)),
})
}

isTrunk, err := b.isTrunk(summary.Header.ID(), summary.Header.Number())
if err != nil {
return err
Expand All @@ -61,7 +82,7 @@ func (b *Blocks) handleGetBlock(w http.ResponseWriter, req *http.Request) error
}

jSummary := buildJSONBlockSummary(summary, isTrunk, isFinalized)
if expanded == "true" {
if expanded {
txs, err := b.repo.GetBlockTransactions(summary.Header.ID())
if err != nil {
return err
Expand Down
55 changes: 55 additions & 0 deletions api/blocks/blocks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package blocks_test

import (
"encoding/hex"
"encoding/json"
"math"
"math/big"
Expand All @@ -15,6 +16,7 @@ import (
"strings"
"testing"

"github.com/ethereum/go-ethereum/rlp"
"github.com/gorilla/mux"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -55,6 +57,8 @@ func TestBlock(t *testing.T) {
"testGetFinalizedBlock": testGetFinalizedBlock,
"testGetJustifiedBlock": testGetJustifiedBlock,
"testGetBlockWithRevisionNumberTooHigh": testGetBlockWithRevisionNumberTooHigh,
"testMutuallyExclusiveQueries": testMutuallyExclusiveQueries,
"testGetRawBlock": testGetRawBlock,
} {
t.Run(name, tt)
}
Expand All @@ -67,6 +71,22 @@ func testBadQueryParams(t *testing.T) {

assert.Equal(t, http.StatusBadRequest, statusCode)
assert.Equal(t, "expanded: should be boolean", strings.TrimSpace(string(res)))

badQueryParams = "?raw=1"
res, statusCode, err = tclient.RawHTTPClient().RawHTTPGet("/blocks/best" + badQueryParams)
require.NoError(t, err)

assert.Equal(t, http.StatusBadRequest, statusCode)
assert.Equal(t, "raw: should be boolean", strings.TrimSpace(string(res)))
}

func testMutuallyExclusiveQueries(t *testing.T) {
badQueryParams := "?expanded=true&raw=true"
leszek-vechain marked this conversation as resolved.
Show resolved Hide resolved
res, statusCode, err := tclient.RawHTTPClient().RawHTTPGet("/blocks/best" + badQueryParams)
require.NoError(t, err)

assert.Equal(t, http.StatusBadRequest, statusCode)
assert.Equal(t, "raw&expanded: Raw and Expanded are mutually exclusive", strings.TrimSpace(string(res)))
}

func testGetBestBlock(t *testing.T) {
Expand All @@ -80,6 +100,41 @@ func testGetBestBlock(t *testing.T) {
assert.Equal(t, http.StatusOK, statusCode)
}

func testGetRawBlock(t *testing.T) {
res, statusCode, err := tclient.RawHTTPClient().RawHTTPGet("/blocks/best?raw=true")
require.NoError(t, err)
rawBlock := new(blocks.JSONRawBlockSummary)
if err := json.Unmarshal(res, &rawBlock); err != nil {
t.Fatal(err)
}

blockBytes, err := hex.DecodeString(rawBlock.Raw[2:len(rawBlock.Raw)])
if err != nil {
t.Fatal(err)
}

header := block.Header{}
err = rlp.DecodeBytes(blockBytes, &header)
if err != nil {
t.Fatal(err)
}

expHeader := blk.Header()
assert.Equal(t, expHeader.Number(), header.Number(), "Number should be equal")
assert.Equal(t, expHeader.ID(), header.ID(), "Hash should be equal")
assert.Equal(t, expHeader.ParentID(), header.ParentID(), "ParentID should be equal")
assert.Equal(t, expHeader.Timestamp(), header.Timestamp(), "Timestamp should be equal")
assert.Equal(t, expHeader.TotalScore(), header.TotalScore(), "TotalScore should be equal")
assert.Equal(t, expHeader.GasLimit(), header.GasLimit(), "GasLimit should be equal")
assert.Equal(t, expHeader.GasUsed(), header.GasUsed(), "GasUsed should be equal")
assert.Equal(t, expHeader.Beneficiary(), header.Beneficiary(), "Beneficiary should be equal")
assert.Equal(t, expHeader.TxsRoot(), header.TxsRoot(), "TxsRoot should be equal")
assert.Equal(t, expHeader.StateRoot(), header.StateRoot(), "StateRoot should be equal")
assert.Equal(t, expHeader.ReceiptsRoot(), header.ReceiptsRoot(), "ReceiptsRoot should be equal")

assert.Equal(t, http.StatusOK, statusCode)
}

func testGetBlockByHeight(t *testing.T) {
res, statusCode, err := tclient.RawHTTPClient().RawHTTPGet("/blocks/1")
require.NoError(t, err)
Expand Down
4 changes: 4 additions & 0 deletions api/blocks/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ type JSONBlockSummary struct {
IsFinalized bool `json:"isFinalized"`
}

type JSONRawBlockSummary struct {
Raw string `json:"raw"`
}

type JSONCollapsedBlock struct {
*JSONBlockSummary
Transactions []thor.Bytes32 `json:"transactions"`
Expand Down
13 changes: 13 additions & 0 deletions api/doc/thor.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ paths:
parameters:
- $ref: '#/components/parameters/RevisionInPath'
- $ref: '#/components/parameters/ExpandedInQuery'
- $ref: '#/components/parameters/RawBlockInQuery'
tags:
- Blocks
summary: Retrieve a block
Expand Down Expand Up @@ -2353,6 +2354,18 @@ components:
type: boolean
example: false

RawBlockInQuery:
name: raw
in: query
required: false
description: |
Whether the block should be returned in RLP encoding or not.
- `true` returns `block` as an RLP encoded object
- `false` returns `block` as a structured JSON object
schema:
type: boolean
example: false

PendingInQuery:
name: pending
in: query
Expand Down
13 changes: 13 additions & 0 deletions api/utils/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"encoding/json"
"io"
"net/http"

"github.com/pkg/errors"
)

type httpError struct {
Expand Down Expand Up @@ -36,6 +38,17 @@ func BadRequest(cause error) error {
}
}

func StringToBoolean(boolStr string, defaultVal bool) (bool, error) {
if boolStr == "" {
return defaultVal, nil
} else if boolStr == "false" {
return false, nil
} else if boolStr == "true" {
otherview marked this conversation as resolved.
Show resolved Hide resolved
return true, nil
}
return false, errors.New("should be boolean")
}

// Forbidden convenience method to create http forbidden error.
func Forbidden(cause error) error {
return &httpError{
Expand Down
Loading