Skip to content

Commit 5397144

Browse files
authored
Merge pull request #6920 from onflow/leo/v0.37-add-query-last-executed-sealed-block
Backport v0.37 add query last executed sealed block
2 parents 4a197c8 + 1fc2011 commit 5397144

File tree

1 file changed

+106
-9
lines changed
  • cmd/util/cmd/read-protocol-state/cmd

1 file changed

+106
-9
lines changed

cmd/util/cmd/read-protocol-state/cmd/blocks.go

Lines changed: 106 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cmd
22

33
import (
4+
"errors"
45
"fmt"
56

67
"github.com/rs/zerolog/log"
@@ -13,10 +14,11 @@ import (
1314
)
1415

1516
var (
16-
flagHeight uint64
17-
flagBlockID string
18-
flagFinal bool
19-
flagSealed bool
17+
flagHeight uint64
18+
flagBlockID string
19+
flagFinal bool
20+
flagSealed bool
21+
flagExecuted bool
2022
)
2123

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

4042
Cmd.Flags().BoolVar(&flagSealed, "sealed", false,
4143
"get sealed block")
44+
45+
Cmd.Flags().BoolVar(&flagExecuted, "executed", false,
46+
"get last executed and sealed block (execution node only)")
4247
}
4348

4449
type Reader struct {
45-
state protocol.State
46-
blocks storage.Blocks
50+
state protocol.State
51+
blocks storage.Blocks
52+
commits storage.Commits
4753
}
4854

4955
func NewReader(state protocol.State, storages *storage.All) *Reader {
5056
return &Reader{
51-
state: state,
52-
blocks: storages.Blocks,
57+
state: state,
58+
blocks: storages.Blocks,
59+
commits: storages.Commits,
5360
}
5461
}
5562

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

111+
func (r *Reader) GetRoot() (*flow.Block, error) {
112+
header := r.state.Params().SealedRoot()
113+
114+
block, err := r.getBlockByHeader(header)
115+
if err != nil {
116+
return nil, fmt.Errorf("could not get block by header: %w", err)
117+
}
118+
return block, nil
119+
}
120+
104121
func (r *Reader) GetBlockByID(blockID flow.Identifier) (*flow.Block, error) {
105122
header, err := r.state.AtBlockID(blockID).Head()
106123
if err != nil {
@@ -114,6 +131,22 @@ func (r *Reader) GetBlockByID(blockID flow.Identifier) (*flow.Block, error) {
114131
return block, nil
115132
}
116133

134+
// IsExecuted returns true if the block is executed
135+
// this only works for execution node.
136+
func (r *Reader) IsExecuted(blockID flow.Identifier) (bool, error) {
137+
_, err := r.commits.ByBlockID(blockID)
138+
if err == nil {
139+
return true, nil
140+
}
141+
142+
// statecommitment not exists means the block hasn't been executed yet
143+
if errors.Is(err, storage.ErrNotFound) {
144+
return false, nil
145+
}
146+
147+
return false, err
148+
}
149+
117150
func run(*cobra.Command, []string) {
118151
db := common.InitStorage(flagDatadir)
119152
defer db.Close()
@@ -126,6 +159,12 @@ func run(*cobra.Command, []string) {
126159

127160
reader := NewReader(state, storages)
128161

162+
// making sure only one flag is being used
163+
err = checkOnlyOneFlagIsUsed(flagHeight, flagBlockID, flagFinal, flagSealed, flagExecuted)
164+
if err != nil {
165+
log.Fatal().Err(err).Msg("could not get block")
166+
}
167+
129168
if flagHeight > 0 {
130169
log.Info().Msgf("get block by height: %v", flagHeight)
131170
block, err := reader.GetBlockByHeight(flagHeight)
@@ -171,5 +210,63 @@ func run(*cobra.Command, []string) {
171210
return
172211
}
173212

174-
log.Fatal().Msgf("missing flag, try --final or --sealed or --height or --block-id")
213+
if flagExecuted {
214+
log.Info().Msgf("get last executed and sealed block")
215+
sealed, err := reader.GetSealed()
216+
if err != nil {
217+
log.Fatal().Err(err).Msg("could not get sealed block")
218+
}
219+
220+
root, err := reader.GetRoot()
221+
if err != nil {
222+
log.Fatal().Err(err).Msg("could not get root block")
223+
}
224+
225+
// find the last executed and sealed block
226+
for h := sealed.Header.Height; h >= root.Header.Height; h-- {
227+
block, err := reader.GetBlockByHeight(h)
228+
if err != nil {
229+
log.Fatal().Err(err).Msgf("could not get block by height: %v", h)
230+
}
231+
232+
executed, err := reader.IsExecuted(block.ID())
233+
if err != nil {
234+
log.Fatal().Err(err).Msgf("could not check block executed or not: %v", h)
235+
}
236+
237+
if executed {
238+
common.PrettyPrintEntity(block)
239+
return
240+
}
241+
}
242+
243+
log.Fatal().Msg("could not find executed block")
244+
}
245+
246+
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")
247+
}
248+
249+
func checkOnlyOneFlagIsUsed(height uint64, blockID string, final, sealed, executed bool) error {
250+
flags := make([]string, 0, 5)
251+
if height > 0 {
252+
flags = append(flags, "height")
253+
}
254+
if blockID != "" {
255+
flags = append(flags, "blockID")
256+
}
257+
if final {
258+
flags = append(flags, "final")
259+
}
260+
if sealed {
261+
flags = append(flags, "sealed")
262+
}
263+
if executed {
264+
flags = append(flags, "executed")
265+
}
266+
267+
if len(flags) != 1 {
268+
return fmt.Errorf("only one flag can be used at a time, used flags: %v", flags)
269+
}
270+
271+
return nil
175272
}

0 commit comments

Comments
 (0)