Skip to content

Commit

Permalink
Merge branch 'feat/index-blocks' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
altergui committed Sep 3, 2024
2 parents ece7951 + 717bb47 commit 7326a87
Show file tree
Hide file tree
Showing 27 changed files with 940 additions and 401 deletions.
2 changes: 2 additions & 0 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ const (
ParamHeight = "height"
ParamReference = "reference"
ParamType = "type"
ParamSubtype = "subtype"
ParamSigner = "signer"
ParamAccountIdFrom = "accountIdFrom"
ParamAccountIdTo = "accountIdTo"
ParamStartDateAfter = "startDateAfter"
Expand Down
21 changes: 12 additions & 9 deletions api/api_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,11 @@ type AccountParams struct {
// TransactionParams allows the client to filter transactions
type TransactionParams struct {
PaginationParams
Height uint64 `json:"height,omitempty"`
Type string `json:"type,omitempty"`
Hash string `json:"hash,omitempty"`
Height uint64 `json:"height,omitempty"`
Type string `json:"type,omitempty"`
Subtype string `json:"subtype,omitempty"`
Signer string `json:"signer,omitempty"`
}

// BlockParams allows the client to filter blocks
Expand Down Expand Up @@ -275,8 +278,8 @@ type TransactionReference struct {

// TransactionsList is used to return a paginated list to the client
type TransactionsList struct {
Transactions []*indexertypes.Transaction `json:"transactions"`
Pagination *Pagination `json:"pagination"`
Transactions []*indexertypes.TransactionMetadata `json:"transactions"`
Pagination *Pagination `json:"pagination"`
}

// FeesList is used to return a paginated list to the client
Expand All @@ -292,9 +295,8 @@ type TransfersList struct {
}

type GenericTransactionWithInfo struct {
TxContent json.RawMessage `json:"tx"`
TxInfo indexertypes.Transaction `json:"txInfo"`
Signature types.HexBytes `json:"signature"`
TxContent json.RawMessage `json:"tx"`
TxInfo *indexertypes.Transaction `json:"txInfo"`
}

type ChainInfo struct {
Expand Down Expand Up @@ -444,8 +446,9 @@ func CensusTypeToOrigin(ctype CensusTypeDescription) (models.CensusOrigin, []byt
}

type Block struct {
comettypes.Block `json:",inline"`
Hash types.HexBytes `json:"hash" `
comettypes.Header `json:"header"`
Hash types.HexBytes `json:"hash" `
TxCount int64 `json:"txCount"`
}

// BlockList is used to return a paginated list to the client
Expand Down
175 changes: 66 additions & 109 deletions api/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,9 @@ import (
"go.vocdoni.io/dvote/crypto/zk/circuit"
"go.vocdoni.io/dvote/httprouter"
"go.vocdoni.io/dvote/httprouter/apirest"
"go.vocdoni.io/dvote/types"
"go.vocdoni.io/dvote/util"
"go.vocdoni.io/dvote/vochain"
"go.vocdoni.io/dvote/vochain/genesis"
"go.vocdoni.io/dvote/vochain/indexer"
"go.vocdoni.io/dvote/vochain/indexer/indexertypes"
"go.vocdoni.io/dvote/vochain/state"
)

Expand Down Expand Up @@ -107,14 +104,6 @@ func (a *API) enableChainHandlers() error {
); err != nil {
return err
}
if err := a.Endpoint.RegisterMethod(
"/chain/transactions/reference/index/{index}",
"GET",
apirest.MethodAccessTypePublic,
a.chainTxRefByIndexHandler,
); err != nil {
return err
}
if err := a.Endpoint.RegisterMethod(
"/chain/blocks/{height}/transactions/page/{page}",
"GET",
Expand Down Expand Up @@ -167,7 +156,7 @@ func (a *API) enableChainHandlers() error {
"/chain/blocks/{height}",
"GET",
apirest.MethodAccessTypePublic,
a.chainBlockHandler,
a.chainBlockByHeightHandler,
); err != nil {
return err
}
Expand Down Expand Up @@ -654,7 +643,7 @@ func (a *API) chainTxRefByHashHandler(_ *apirest.APIdata, ctx *httprouter.HTTPCo
if err != nil {
return err
}
ref, err := a.indexer.GetTxHashReference(hash)
ref, err := a.indexer.GetTxMetadataByHash(hash)
if err != nil {
if errors.Is(err, indexer.ErrTransactionNotFound) {
return ErrTransactionNotFound
Expand Down Expand Up @@ -690,25 +679,16 @@ func (a *API) chainTxHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) er
if err != nil {
return err
}
stx, err := a.vocapp.GetTx(uint32(height), int32(index))
if err != nil {
if errors.Is(err, vochain.ErrTransactionNotFound) {
return ErrTransactionNotFound
}
return ErrVochainGetTxFailed.WithErr(err)
}

ref, err := a.indexer.GetTxReferenceByBlockHeightAndBlockIndex(height, index)
ref, err := a.indexer.GetTransactionByHeightAndIndex(height, index)
if err != nil {
if errors.Is(err, indexer.ErrTransactionNotFound) {
return ErrTransactionNotFound
}
return ErrVochainGetTxFailed.WithErr(err)
}
tx := &GenericTransactionWithInfo{
TxContent: protoTxAsJSON(stx.Tx),
Signature: stx.Signature,
TxInfo: *ref,
TxContent: protoTxAsJSON(ref.RawTx),
TxInfo: ref,
}
data, err := json.Marshal(tx)
if err != nil {
Expand All @@ -717,36 +697,6 @@ func (a *API) chainTxHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) er
return ctx.Send(data, apirest.HTTPstatusOK)
}

// chainTxRefByIndexHandler
//
// @Summary Transaction by index
// @Description Get transaction by its index. This is not transaction reference (hash), and neither the block height and block index. The transaction index is an incremental counter for each transaction. You could use the transaction `block` and `index` to retrieve full info using [transaction by block and index](transaction-by-block-index).
// @Tags Chain
// @Accept json
// @Produce json
// @Param index path int true "Index of the transaction"
// @Success 200 {object} indexertypes.Transaction
// @Success 204 "See [errors](vocdoni-api#errors) section"
// @Router /chain/transactions/reference/index/{index} [get]
func (a *API) chainTxRefByIndexHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error {
index, err := strconv.ParseUint(ctx.URLParam("index"), 10, 64)
if err != nil {
return err
}
ref, err := a.indexer.GetTransaction(index)
if err != nil {
if errors.Is(err, indexer.ErrTransactionNotFound) {
return ErrTransactionNotFound
}
return ErrVochainGetTxFailed.WithErr(err)
}
data, err := json.Marshal(ref)
if err != nil {
return err
}
return ctx.Send(data, apirest.HTTPstatusOK)
}

// chainTxListHandler
//
// @Summary List transactions
Expand All @@ -758,14 +708,19 @@ func (a *API) chainTxRefByIndexHandler(_ *apirest.APIdata, ctx *httprouter.HTTPC
// @Param limit query number false "Items per page"
// @Param height query number false "Block height"
// @Param type query string false "Tx type"
// @Param subtype query string false "Tx subtype"
// @Param signer query string false "Tx signer"
// @Success 200 {object} TransactionsList "List of transactions references"
// @Router /chain/transactions [get]
func (a *API) chainTxListHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error {
params, err := parseTransactionParams(
ctx.QueryParam(ParamPage),
ctx.QueryParam(ParamLimit),
ctx.QueryParam(ParamHash),
ctx.QueryParam(ParamHeight),
ctx.QueryParam(ParamType),
ctx.QueryParam(ParamSubtype),
ctx.QueryParam(ParamSigner),
)
if err != nil {
return err
Expand Down Expand Up @@ -797,6 +752,9 @@ func (a *API) chainTxListByPageHandler(_ *apirest.APIdata, ctx *httprouter.HTTPC
"",
"",
"",
"",
"",
"",
)
if err != nil {
return err
Expand Down Expand Up @@ -833,6 +791,9 @@ func (a *API) chainTxListByHeightAndPageHandler(_ *apirest.APIdata, ctx *httprou
"",
ctx.URLParam(ParamHeight),
"",
"",
"",
"",
)
if err != nil {
return err
Expand All @@ -858,7 +819,10 @@ func (a *API) transactionList(params *TransactionParams) (*TransactionsList, err
params.Limit,
params.Page*params.Limit,
params.Height,
params.Hash,
params.Type,
params.Subtype,
params.Signer,
)
if err != nil {
return nil, ErrIndexerQueryFailed.WithErr(err)
Expand Down Expand Up @@ -911,7 +875,7 @@ func (a *API) chainValidatorsHandler(_ *apirest.APIdata, ctx *httprouter.HTTPCon
return ctx.Send(data, apirest.HTTPstatusOK)
}

// chainBlockHandler
// chainBlockByHeightHandler
//
// @Summary Get block (by height)
// @Description Returns the full block information at the given height
Expand All @@ -921,23 +885,34 @@ func (a *API) chainValidatorsHandler(_ *apirest.APIdata, ctx *httprouter.HTTPCon
// @Param height path int true "Block height"
// @Success 200 {object} api.Block
// @Router /chain/blocks/{height} [get]
func (a *API) chainBlockHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error {
func (a *API) chainBlockByHeightHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error {
height, err := strconv.ParseUint(ctx.URLParam(ParamHeight), 10, 64)
if err != nil {
return err
}
tmblock := a.vocapp.GetBlockByHeight(int64(height))
if tmblock == nil {
return ErrBlockNotFound
idxblock, err := a.indexer.BlockByHeight(int64(height))
if err != nil {
if errors.Is(err, indexer.ErrBlockNotFound) {
return ErrBlockNotFound
}
return ErrBlockNotFound.WithErr(err)
}
txcount, err := a.indexer.CountTransactionsByHeight(int64(height))
if err != nil {
return ErrIndexerQueryFailed.WithErr(err)
}
block := &Block{
Block: comettypes.Block{
Header: tmblock.Header,
Data: tmblock.Data,
Evidence: tmblock.Evidence,
LastCommit: tmblock.LastCommit,
Header: comettypes.Header{
ChainID: idxblock.ChainID,
Height: idxblock.Height,
Time: idxblock.Time,
ProposerAddress: []byte(idxblock.ProposerAddress),
LastBlockID: comettypes.BlockID{
Hash: []byte(idxblock.LastBlockHash),
},
},
Hash: types.HexBytes(tmblock.Hash()),
Hash: idxblock.Hash,
TxCount: txcount,
}
data, err := json.Marshal(block)
if err != nil {
Expand All @@ -961,18 +936,29 @@ func (a *API) chainBlockByHashHandler(_ *apirest.APIdata, ctx *httprouter.HTTPCo
if err != nil {
return err
}
tmblock := a.vocapp.GetBlockByHash(hash)
if tmblock == nil {
return ErrBlockNotFound
idxblock, err := a.indexer.BlockByHash(hash)
if err != nil {
if errors.Is(err, indexer.ErrBlockNotFound) {
return ErrBlockNotFound
}
return ErrBlockNotFound.WithErr(err)
}
txcount, err := a.indexer.CountTransactionsByHeight(idxblock.Height)
if err != nil {
return ErrIndexerQueryFailed.WithErr(err)
}
block := &Block{
Block: comettypes.Block{
Header: tmblock.Header,
Data: tmblock.Data,
Evidence: tmblock.Evidence,
LastCommit: tmblock.LastCommit,
Header: comettypes.Header{
ChainID: idxblock.ChainID,
Height: idxblock.Height,
Time: idxblock.Time,
ProposerAddress: []byte(idxblock.ProposerAddress),
LastBlockID: comettypes.BlockID{
Hash: []byte(idxblock.LastBlockHash),
},
},
Hash: types.HexBytes(tmblock.Hash()),
Hash: idxblock.Hash,
TxCount: txcount,
}
data, err := json.Marshal(block)
if err != nil {
Expand Down Expand Up @@ -1015,39 +1001,7 @@ func (a *API) chainBlockListHandler(_ *apirest.APIdata, ctx *httprouter.HTTPCont
//
// Errors returned are always of type APIerror.
func (a *API) sendBlockList(ctx *httprouter.HTTPContext, params *BlockParams) error {
// TODO: replace this by a.indexer.BlockList when it's available
blockList := func(limit, offset int, _, _, _ string) ([]*indexertypes.Block, uint64, error) {
if offset < 0 {
return nil, 0, fmt.Errorf("invalid value: offset cannot be %d", offset)
}
if limit <= 0 {
return nil, 0, fmt.Errorf("invalid value: limit cannot be %d", limit)
}
height := a.vocapp.Height()
total := uint64(height) - uint64(a.vocapp.Node.BlockStore().Base())
start := height - uint32(params.Page*params.Limit)
end := start - uint32(params.Limit)
list := []*indexertypes.Block{}
for h := start; h > end; h-- {
tmblock := a.vocapp.GetBlockByHeight(int64(h))
if tmblock == nil {
break
}
list = append(list, &indexertypes.Block{
ChainID: tmblock.ChainID,
Height: tmblock.Height,
Time: tmblock.Time,
Hash: types.HexBytes(tmblock.Hash()),
ProposerAddress: tmblock.ProposerAddress.Bytes(),
LastBlockHash: tmblock.LastBlockID.Hash.Bytes(),
TxCount: int64(len(tmblock.Txs)),
})
}

return list, uint64(total), nil
}

blocks, total, err := blockList(
blocks, total, err := a.indexer.BlockList(
params.Limit,
params.Page*params.Limit,
params.ChainID,
Expand Down Expand Up @@ -1401,7 +1355,7 @@ func parseTransfersParams(paramPage, paramLimit, paramAccountId, paramAccountIdF
}

// parseTransactionParams returns an TransactionParams filled with the passed params
func parseTransactionParams(paramPage, paramLimit, paramHeight, paramType string) (*TransactionParams, error) {
func parseTransactionParams(paramPage, paramLimit, paramHash, paramHeight, paramType, paramSubtype, paramSigner string) (*TransactionParams, error) {
pagination, err := parsePaginationParams(paramPage, paramLimit)
if err != nil {
return nil, err
Expand All @@ -1414,8 +1368,11 @@ func parseTransactionParams(paramPage, paramLimit, paramHeight, paramType string

return &TransactionParams{
PaginationParams: pagination,
Hash: util.TrimHex(paramHash),
Height: uint64(height),
Type: paramType,
Subtype: paramSubtype,
Signer: util.TrimHex(paramSigner),
}, nil
}

Expand Down
Loading

0 comments on commit 7326a87

Please sign in to comment.