Skip to content

Commit 78dc107

Browse files
committed
api: fetch blocks and transactions from indexer rather than app BlockStore
these endpoints now fetch blocks from indexer, return just `header` and include `txCount` * /chain/blocks * /chain/blocks/{height} * /chain/blocks/hash/{hash} this endpoint now fetches the full tx from indexer, and includes `subtype` and `signer` fields * /chain/transactions/{height}/{index} this endpoint now accepts more filter params (subtype, signer) * /chain/transactions refactor: * api: rename chainBlockHandler -> chainBlockByHeightHandler
1 parent 4b1340f commit 78dc107

File tree

4 files changed

+105
-76
lines changed

4 files changed

+105
-76
lines changed

api/api.go

+2
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ const (
7777
ParamHeight = "height"
7878
ParamReference = "reference"
7979
ParamType = "type"
80+
ParamSubtype = "subtype"
81+
ParamSigner = "signer"
8082
ParamAccountIdFrom = "accountIdFrom"
8183
ParamAccountIdTo = "accountIdTo"
8284
ParamStartDateAfter = "startDateAfter"

api/api_types.go

+9-7
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,10 @@ type AccountParams struct {
5050
// TransactionParams allows the client to filter transactions
5151
type TransactionParams struct {
5252
PaginationParams
53-
Height uint64 `json:"height,omitempty"`
54-
Type string `json:"type,omitempty"`
53+
Height uint64 `json:"height,omitempty"`
54+
Type string `json:"type,omitempty"`
55+
Subtype string `json:"subtype,omitempty"`
56+
Signer string `json:"signer,omitempty"`
5557
}
5658

5759
// BlockParams allows the client to filter blocks
@@ -292,9 +294,8 @@ type TransfersList struct {
292294
}
293295

294296
type GenericTransactionWithInfo struct {
295-
TxContent json.RawMessage `json:"tx"`
296-
TxInfo indexertypes.Transaction `json:"txInfo"`
297-
Signature types.HexBytes `json:"signature"`
297+
TxContent json.RawMessage `json:"tx"`
298+
TxInfo *indexertypes.Transaction `json:"txInfo"`
298299
}
299300

300301
type ChainInfo struct {
@@ -444,8 +445,9 @@ func CensusTypeToOrigin(ctype CensusTypeDescription) (models.CensusOrigin, []byt
444445
}
445446

446447
type Block struct {
447-
comettypes.Block `json:",inline"`
448-
Hash types.HexBytes `json:"hash" `
448+
comettypes.Header `json:"header"`
449+
Hash types.HexBytes `json:"hash" `
450+
TxCount int64 `json:"txCount"`
449451
}
450452

451453
// BlockList is used to return a paginated list to the client

api/chain.go

+59-69
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,9 @@ import (
1313
"go.vocdoni.io/dvote/crypto/zk/circuit"
1414
"go.vocdoni.io/dvote/httprouter"
1515
"go.vocdoni.io/dvote/httprouter/apirest"
16-
"go.vocdoni.io/dvote/types"
1716
"go.vocdoni.io/dvote/util"
18-
"go.vocdoni.io/dvote/vochain"
1917
"go.vocdoni.io/dvote/vochain/genesis"
2018
"go.vocdoni.io/dvote/vochain/indexer"
21-
"go.vocdoni.io/dvote/vochain/indexer/indexertypes"
2219
"go.vocdoni.io/dvote/vochain/state"
2320
)
2421

@@ -167,7 +164,7 @@ func (a *API) enableChainHandlers() error {
167164
"/chain/blocks/{height}",
168165
"GET",
169166
apirest.MethodAccessTypePublic,
170-
a.chainBlockHandler,
167+
a.chainBlockByHeightHandler,
171168
); err != nil {
172169
return err
173170
}
@@ -690,14 +687,6 @@ func (a *API) chainTxHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) er
690687
if err != nil {
691688
return err
692689
}
693-
stx, err := a.vocapp.GetTx(uint32(height), int32(index))
694-
if err != nil {
695-
if errors.Is(err, vochain.ErrTransactionNotFound) {
696-
return ErrTransactionNotFound
697-
}
698-
return ErrVochainGetTxFailed.WithErr(err)
699-
}
700-
701690
ref, err := a.indexer.GetTransactionByHeightAndIndex(height, index)
702691
if err != nil {
703692
if errors.Is(err, indexer.ErrTransactionNotFound) {
@@ -706,9 +695,8 @@ func (a *API) chainTxHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) er
706695
return ErrVochainGetTxFailed.WithErr(err)
707696
}
708697
tx := &GenericTransactionWithInfo{
709-
TxContent: []byte(protoFormat(stx.Tx)),
710-
Signature: stx.Signature,
711-
TxInfo: *ref,
698+
TxContent: []byte(protoFormat(ref.RawTx)),
699+
TxInfo: ref,
712700
}
713701
data, err := json.Marshal(tx)
714702
if err != nil {
@@ -758,6 +746,8 @@ func (a *API) chainTxRefByIndexHandler(_ *apirest.APIdata, ctx *httprouter.HTTPC
758746
// @Param limit query number false "Items per page"
759747
// @Param height query number false "Block height"
760748
// @Param type query string false "Tx type"
749+
// @Param subtype query string false "Tx subtype"
750+
// @Param signer query string false "Tx signer"
761751
// @Success 200 {object} TransactionsList "List of transactions references"
762752
// @Router /chain/transactions [get]
763753
func (a *API) chainTxListHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error {
@@ -766,6 +756,8 @@ func (a *API) chainTxListHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext
766756
ctx.QueryParam(ParamLimit),
767757
ctx.QueryParam(ParamHeight),
768758
ctx.QueryParam(ParamType),
759+
ctx.QueryParam(ParamSubtype),
760+
ctx.QueryParam(ParamSigner),
769761
)
770762
if err != nil {
771763
return err
@@ -797,6 +789,8 @@ func (a *API) chainTxListByPageHandler(_ *apirest.APIdata, ctx *httprouter.HTTPC
797789
"",
798790
"",
799791
"",
792+
"",
793+
"",
800794
)
801795
if err != nil {
802796
return err
@@ -833,6 +827,8 @@ func (a *API) chainTxListByHeightAndPageHandler(_ *apirest.APIdata, ctx *httprou
833827
"",
834828
ctx.URLParam(ParamHeight),
835829
"",
830+
"",
831+
"",
836832
)
837833
if err != nil {
838834
return err
@@ -859,6 +855,8 @@ func (a *API) transactionList(params *TransactionParams) (*TransactionsList, err
859855
params.Page*params.Limit,
860856
params.Height,
861857
params.Type,
858+
params.Subtype,
859+
params.Signer,
862860
)
863861
if err != nil {
864862
return nil, ErrIndexerQueryFailed.WithErr(err)
@@ -911,7 +909,7 @@ func (a *API) chainValidatorsHandler(_ *apirest.APIdata, ctx *httprouter.HTTPCon
911909
return ctx.Send(data, apirest.HTTPstatusOK)
912910
}
913911

914-
// chainBlockHandler
912+
// chainBlockByHeightHandler
915913
//
916914
// @Summary Get block (by height)
917915
// @Description Returns the full block information at the given height
@@ -921,23 +919,34 @@ func (a *API) chainValidatorsHandler(_ *apirest.APIdata, ctx *httprouter.HTTPCon
921919
// @Param height path int true "Block height"
922920
// @Success 200 {object} api.Block
923921
// @Router /chain/blocks/{height} [get]
924-
func (a *API) chainBlockHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error {
922+
func (a *API) chainBlockByHeightHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error {
925923
height, err := strconv.ParseUint(ctx.URLParam(ParamHeight), 10, 64)
926924
if err != nil {
927925
return err
928926
}
929-
tmblock := a.vocapp.GetBlockByHeight(int64(height))
930-
if tmblock == nil {
931-
return ErrBlockNotFound
927+
idxblock, err := a.indexer.BlockByHeight(int64(height))
928+
if err != nil {
929+
if errors.Is(err, indexer.ErrBlockNotFound) {
930+
return ErrBlockNotFound
931+
}
932+
return ErrBlockNotFound.WithErr(err)
933+
}
934+
txcount, err := a.indexer.CountTransactionsByHeight(int64(height))
935+
if err != nil {
936+
return ErrIndexerQueryFailed.WithErr(err)
932937
}
933938
block := &Block{
934-
Block: comettypes.Block{
935-
Header: tmblock.Header,
936-
Data: tmblock.Data,
937-
Evidence: tmblock.Evidence,
938-
LastCommit: tmblock.LastCommit,
939+
Header: comettypes.Header{
940+
ChainID: idxblock.ChainID,
941+
Height: idxblock.Height,
942+
Time: idxblock.Time,
943+
ProposerAddress: []byte(idxblock.ProposerAddress),
944+
LastBlockID: comettypes.BlockID{
945+
Hash: []byte(idxblock.LastBlockHash),
946+
},
939947
},
940-
Hash: types.HexBytes(tmblock.Hash()),
948+
Hash: idxblock.Hash,
949+
TxCount: txcount,
941950
}
942951
data, err := json.Marshal(block)
943952
if err != nil {
@@ -961,18 +970,29 @@ func (a *API) chainBlockByHashHandler(_ *apirest.APIdata, ctx *httprouter.HTTPCo
961970
if err != nil {
962971
return err
963972
}
964-
tmblock := a.vocapp.GetBlockByHash(hash)
965-
if tmblock == nil {
966-
return ErrBlockNotFound
973+
idxblock, err := a.indexer.BlockByHash(hash)
974+
if err != nil {
975+
if errors.Is(err, indexer.ErrBlockNotFound) {
976+
return ErrBlockNotFound
977+
}
978+
return ErrBlockNotFound.WithErr(err)
979+
}
980+
txcount, err := a.indexer.CountTransactionsByHeight(idxblock.Height)
981+
if err != nil {
982+
return ErrIndexerQueryFailed.WithErr(err)
967983
}
968984
block := &Block{
969-
Block: comettypes.Block{
970-
Header: tmblock.Header,
971-
Data: tmblock.Data,
972-
Evidence: tmblock.Evidence,
973-
LastCommit: tmblock.LastCommit,
985+
Header: comettypes.Header{
986+
ChainID: idxblock.ChainID,
987+
Height: idxblock.Height,
988+
Time: idxblock.Time,
989+
ProposerAddress: []byte(idxblock.ProposerAddress),
990+
LastBlockID: comettypes.BlockID{
991+
Hash: []byte(idxblock.LastBlockHash),
992+
},
974993
},
975-
Hash: types.HexBytes(tmblock.Hash()),
994+
Hash: idxblock.Hash,
995+
TxCount: txcount,
976996
}
977997
data, err := json.Marshal(block)
978998
if err != nil {
@@ -1015,39 +1035,7 @@ func (a *API) chainBlockListHandler(_ *apirest.APIdata, ctx *httprouter.HTTPCont
10151035
//
10161036
// Errors returned are always of type APIerror.
10171037
func (a *API) sendBlockList(ctx *httprouter.HTTPContext, params *BlockParams) error {
1018-
// TODO: replace this by a.indexer.BlockList when it's available
1019-
blockList := func(limit, offset int, _, _, _ string) ([]*indexertypes.Block, uint64, error) {
1020-
if offset < 0 {
1021-
return nil, 0, fmt.Errorf("invalid value: offset cannot be %d", offset)
1022-
}
1023-
if limit <= 0 {
1024-
return nil, 0, fmt.Errorf("invalid value: limit cannot be %d", limit)
1025-
}
1026-
height := a.vocapp.Height()
1027-
total := uint64(height) - uint64(a.vocapp.Node.BlockStore().Base())
1028-
start := height - uint32(params.Page*params.Limit)
1029-
end := start - uint32(params.Limit)
1030-
list := []*indexertypes.Block{}
1031-
for h := start; h > end; h-- {
1032-
tmblock := a.vocapp.GetBlockByHeight(int64(h))
1033-
if tmblock == nil {
1034-
break
1035-
}
1036-
list = append(list, &indexertypes.Block{
1037-
ChainID: tmblock.ChainID,
1038-
Height: tmblock.Height,
1039-
Time: tmblock.Time,
1040-
Hash: types.HexBytes(tmblock.Hash()),
1041-
ProposerAddress: tmblock.ProposerAddress.Bytes(),
1042-
LastBlockHash: tmblock.LastBlockID.Hash.Bytes(),
1043-
TxCount: int64(len(tmblock.Txs)),
1044-
})
1045-
}
1046-
1047-
return list, uint64(total), nil
1048-
}
1049-
1050-
blocks, total, err := blockList(
1038+
blocks, total, err := a.indexer.BlockList(
10511039
params.Limit,
10521040
params.Page*params.Limit,
10531041
params.ChainID,
@@ -1401,7 +1389,7 @@ func parseTransfersParams(paramPage, paramLimit, paramAccountId, paramAccountIdF
14011389
}
14021390

14031391
// parseTransactionParams returns an TransactionParams filled with the passed params
1404-
func parseTransactionParams(paramPage, paramLimit, paramHeight, paramType string) (*TransactionParams, error) {
1392+
func parseTransactionParams(paramPage, paramLimit, paramHeight, paramType, paramSubtype, paramSigner string) (*TransactionParams, error) {
14051393
pagination, err := parsePaginationParams(paramPage, paramLimit)
14061394
if err != nil {
14071395
return nil, err
@@ -1416,6 +1404,8 @@ func parseTransactionParams(paramPage, paramLimit, paramHeight, paramType string
14161404
PaginationParams: pagination,
14171405
Height: uint64(height),
14181406
Type: paramType,
1407+
Subtype: paramSubtype,
1408+
Signer: paramSigner,
14191409
}, nil
14201410
}
14211411

test/api_test.go

+35
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,41 @@ func TestAPIAccountTokentxs(t *testing.T) {
461461
qt.Assert(t, gotAcct1.Balance, qt.Equals, initBalance+amountAcc2toAcct1-amountAcc1toAcct2-uint64(txBasePrice))
462462
}
463463

464+
func TestAPIBlocks(t *testing.T) {
465+
server := testcommon.APIserver{}
466+
server.Start(t,
467+
api.ChainHandler,
468+
api.CensusHandler,
469+
api.VoteHandler,
470+
api.AccountHandler,
471+
api.ElectionHandler,
472+
api.WalletHandler,
473+
)
474+
token1 := uuid.New()
475+
c := testutil.NewTestHTTPclient(t, server.ListenAddr, &token1)
476+
477+
// Block 1
478+
server.VochainAPP.AdvanceTestBlock()
479+
waitUntilHeight(t, c, 1)
480+
481+
// create a new account
482+
initBalance := uint64(80)
483+
_ = createAccount(t, c, server, initBalance)
484+
485+
// Block 2
486+
server.VochainAPP.AdvanceTestBlock()
487+
waitUntilHeight(t, c, 2)
488+
489+
// check the txCount
490+
resp, code := c.Request("GET", nil, "chain", "blocks", "1")
491+
qt.Assert(t, code, qt.Equals, 200, qt.Commentf("response: %s", resp))
492+
493+
block := api.Block{}
494+
err := json.Unmarshal(resp, &block)
495+
qt.Assert(t, err, qt.IsNil)
496+
qt.Assert(t, block.TxCount, qt.Equals, int64(1))
497+
}
498+
464499
func runAPIElectionCostWithParams(t *testing.T,
465500
electionParams electionprice.ElectionParameters,
466501
startBlock uint32, initialBalance,

0 commit comments

Comments
 (0)