Skip to content

Commit

Permalink
Merge pull request #6920 from onflow/leo/v0.37-add-query-last-execute…
Browse files Browse the repository at this point in the history
…d-sealed-block

Backport v0.37 add query last executed sealed block
  • Loading branch information
zhangchiqing authored Jan 22, 2025
2 parents 4a197c8 + 1fc2011 commit 5397144
Showing 1 changed file with 106 additions and 9 deletions.
115 changes: 106 additions & 9 deletions cmd/util/cmd/read-protocol-state/cmd/blocks.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"errors"
"fmt"

"github.com/rs/zerolog/log"
Expand All @@ -13,10 +14,11 @@ import (
)

var (
flagHeight uint64
flagBlockID string
flagFinal bool
flagSealed bool
flagHeight uint64
flagBlockID string
flagFinal bool
flagSealed bool
flagExecuted bool
)

var Cmd = &cobra.Command{
Expand All @@ -39,17 +41,22 @@ func init() {

Cmd.Flags().BoolVar(&flagSealed, "sealed", false,
"get sealed block")

Cmd.Flags().BoolVar(&flagExecuted, "executed", false,
"get last executed and sealed block (execution node only)")
}

type Reader struct {
state protocol.State
blocks storage.Blocks
state protocol.State
blocks storage.Blocks
commits storage.Commits
}

func NewReader(state protocol.State, storages *storage.All) *Reader {
return &Reader{
state: state,
blocks: storages.Blocks,
state: state,
blocks: storages.Blocks,
commits: storages.Commits,
}
}

Expand Down Expand Up @@ -101,6 +108,16 @@ func (r *Reader) GetSealed() (*flow.Block, error) {
return block, nil
}

func (r *Reader) GetRoot() (*flow.Block, error) {
header := r.state.Params().SealedRoot()

block, err := r.getBlockByHeader(header)
if err != nil {
return nil, fmt.Errorf("could not get block by header: %w", err)
}
return block, nil
}

func (r *Reader) GetBlockByID(blockID flow.Identifier) (*flow.Block, error) {
header, err := r.state.AtBlockID(blockID).Head()
if err != nil {
Expand All @@ -114,6 +131,22 @@ func (r *Reader) GetBlockByID(blockID flow.Identifier) (*flow.Block, error) {
return block, nil
}

// IsExecuted returns true if the block is executed
// this only works for execution node.
func (r *Reader) IsExecuted(blockID flow.Identifier) (bool, error) {
_, err := r.commits.ByBlockID(blockID)
if err == nil {
return true, nil
}

// statecommitment not exists means the block hasn't been executed yet
if errors.Is(err, storage.ErrNotFound) {
return false, nil
}

return false, err
}

func run(*cobra.Command, []string) {
db := common.InitStorage(flagDatadir)
defer db.Close()
Expand All @@ -126,6 +159,12 @@ func run(*cobra.Command, []string) {

reader := NewReader(state, storages)

// making sure only one flag is being used
err = checkOnlyOneFlagIsUsed(flagHeight, flagBlockID, flagFinal, flagSealed, flagExecuted)
if err != nil {
log.Fatal().Err(err).Msg("could not get block")
}

if flagHeight > 0 {
log.Info().Msgf("get block by height: %v", flagHeight)
block, err := reader.GetBlockByHeight(flagHeight)
Expand Down Expand Up @@ -171,5 +210,63 @@ func run(*cobra.Command, []string) {
return
}

log.Fatal().Msgf("missing flag, try --final or --sealed or --height or --block-id")
if flagExecuted {
log.Info().Msgf("get last executed and sealed block")
sealed, err := reader.GetSealed()
if err != nil {
log.Fatal().Err(err).Msg("could not get sealed block")
}

root, err := reader.GetRoot()
if err != nil {
log.Fatal().Err(err).Msg("could not get root block")
}

// find the last executed and sealed block
for h := sealed.Header.Height; h >= root.Header.Height; h-- {
block, err := reader.GetBlockByHeight(h)
if err != nil {
log.Fatal().Err(err).Msgf("could not get block by height: %v", h)
}

executed, err := reader.IsExecuted(block.ID())
if err != nil {
log.Fatal().Err(err).Msgf("could not check block executed or not: %v", h)
}

if executed {
common.PrettyPrintEntity(block)
return
}
}

log.Fatal().Msg("could not find executed block")
}

log.Fatal().Msgf("missing flag, try --final or --sealed or --height or --executed or --block-id, note that only one flag can be used at a time")
}

func checkOnlyOneFlagIsUsed(height uint64, blockID string, final, sealed, executed bool) error {
flags := make([]string, 0, 5)
if height > 0 {
flags = append(flags, "height")
}
if blockID != "" {
flags = append(flags, "blockID")
}
if final {
flags = append(flags, "final")
}
if sealed {
flags = append(flags, "sealed")
}
if executed {
flags = append(flags, "executed")
}

if len(flags) != 1 {
return fmt.Errorf("only one flag can be used at a time, used flags: %v", flags)
}

return nil
}

0 comments on commit 5397144

Please sign in to comment.