From bc05609157e65f19fada71f1a01d8278dfc5a71c Mon Sep 17 00:00:00 2001 From: "Leo Zhang (zhangchiqing)" Date: Tue, 7 Jan 2025 10:28:56 -0800 Subject: [PATCH 1/5] add --executed to read-protocol-state cmd --- .../cmd/read-protocol-state/cmd/blocks.go | 79 ++++++++++++++++--- 1 file changed, 70 insertions(+), 9 deletions(-) diff --git a/cmd/util/cmd/read-protocol-state/cmd/blocks.go b/cmd/util/cmd/read-protocol-state/cmd/blocks.go index 8395a977969..288ee384d7d 100644 --- a/cmd/util/cmd/read-protocol-state/cmd/blocks.go +++ b/cmd/util/cmd/read-protocol-state/cmd/blocks.go @@ -1,6 +1,7 @@ package cmd import ( + "errors" "fmt" "github.com/rs/zerolog/log" @@ -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{ @@ -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") } 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, } } @@ -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 { @@ -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() @@ -171,5 +204,33 @@ 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") + } + + for h := sealed.Header.Height; h >= uint64(0); 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 + } + } + + // use binary search to find the last executed and sealed block + + } + + log.Fatal().Msgf("missing flag, try --final or --sealed or --height or --executed or --block-id") } From b8aa28fb107c4ee5e19bf3ef0817f948121012c5 Mon Sep 17 00:00:00 2001 From: "Leo Zhang (zhangchiqing)" Date: Tue, 7 Jan 2025 12:03:19 -0800 Subject: [PATCH 2/5] use GetRoot --- cmd/util/cmd/read-protocol-state/cmd/blocks.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cmd/util/cmd/read-protocol-state/cmd/blocks.go b/cmd/util/cmd/read-protocol-state/cmd/blocks.go index 288ee384d7d..aabc351bf13 100644 --- a/cmd/util/cmd/read-protocol-state/cmd/blocks.go +++ b/cmd/util/cmd/read-protocol-state/cmd/blocks.go @@ -211,7 +211,12 @@ func run(*cobra.Command, []string) { log.Fatal().Err(err).Msg("could not get sealed block") } - for h := sealed.Header.Height; h >= uint64(0); h-- { + root, err := reader.GetRoot() + if err != nil { + log.Fatal().Err(err).Msg("could not get root 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) From e1a6abb09f3f51479c60887e7b4fd7788d052bf3 Mon Sep 17 00:00:00 2001 From: "Leo Zhang (zhangchiqing)" Date: Tue, 7 Jan 2025 12:05:00 -0800 Subject: [PATCH 3/5] add error log --- cmd/util/cmd/read-protocol-state/cmd/blocks.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/util/cmd/read-protocol-state/cmd/blocks.go b/cmd/util/cmd/read-protocol-state/cmd/blocks.go index aabc351bf13..fee27740f68 100644 --- a/cmd/util/cmd/read-protocol-state/cmd/blocks.go +++ b/cmd/util/cmd/read-protocol-state/cmd/blocks.go @@ -216,6 +216,7 @@ func run(*cobra.Command, []string) { 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 { @@ -233,8 +234,7 @@ func run(*cobra.Command, []string) { } } - // use binary search to find the last executed and sealed block - + log.Fatal().Msg("could not find executed block") } log.Fatal().Msgf("missing flag, try --final or --sealed or --height or --executed or --block-id") From 4facb8e56ae406c5126b260786a2265b474c2413 Mon Sep 17 00:00:00 2001 From: Leo Zhang Date: Wed, 8 Jan 2025 09:31:51 -0800 Subject: [PATCH 4/5] Update cmd/util/cmd/read-protocol-state/cmd/blocks.go Co-authored-by: Jordan Schalm --- cmd/util/cmd/read-protocol-state/cmd/blocks.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/util/cmd/read-protocol-state/cmd/blocks.go b/cmd/util/cmd/read-protocol-state/cmd/blocks.go index fee27740f68..305774d5776 100644 --- a/cmd/util/cmd/read-protocol-state/cmd/blocks.go +++ b/cmd/util/cmd/read-protocol-state/cmd/blocks.go @@ -43,7 +43,7 @@ func init() { "get sealed block") Cmd.Flags().BoolVar(&flagExecuted, "executed", false, - "get last executed and sealed block") + "get last executed and sealed block (execution node only)") } type Reader struct { From 1fc2011a52716d0955a9dc32955ddfc517916bc2 Mon Sep 17 00:00:00 2001 From: "Leo Zhang (zhangchiqing)" Date: Mon, 13 Jan 2025 09:43:08 -0800 Subject: [PATCH 5/5] check only one flag is used --- .../cmd/read-protocol-state/cmd/blocks.go | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/cmd/util/cmd/read-protocol-state/cmd/blocks.go b/cmd/util/cmd/read-protocol-state/cmd/blocks.go index 305774d5776..2db4172d536 100644 --- a/cmd/util/cmd/read-protocol-state/cmd/blocks.go +++ b/cmd/util/cmd/read-protocol-state/cmd/blocks.go @@ -159,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) @@ -237,5 +243,30 @@ func run(*cobra.Command, []string) { log.Fatal().Msg("could not find executed block") } - log.Fatal().Msgf("missing flag, try --final or --sealed or --height or --executed or --block-id") + 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 }