github.com/onflow/flow-go@v0.33.17/admin/commands/storage/read_blocks.go (about) 1 package storage 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/rs/zerolog/log" 8 9 "github.com/onflow/flow-go/admin" 10 "github.com/onflow/flow-go/admin/commands" 11 "github.com/onflow/flow-go/model/flow" 12 "github.com/onflow/flow-go/state/protocol" 13 "github.com/onflow/flow-go/storage" 14 ) 15 16 var _ commands.AdminCommand = (*ReadBlocksCommand)(nil) 17 18 type readBlocksRequest struct { 19 blocksRequest *blocksRequest 20 numBlocksToQuery uint64 21 } 22 23 type ReadBlocksCommand struct { 24 state protocol.State 25 blocks storage.Blocks 26 } 27 28 func (r *ReadBlocksCommand) Handler(ctx context.Context, req *admin.CommandRequest) (interface{}, error) { 29 data := req.ValidatorData.(*readBlocksRequest) 30 var result []*flow.Block 31 var blockID flow.Identifier 32 33 log.Info().Str("module", "admin-tool").Msgf("read blocks, data: %v", data) 34 35 if header, err := getBlockHeader(r.state, data.blocksRequest); err != nil { 36 return nil, fmt.Errorf("failed to get block header: %w", err) 37 } else { 38 blockID = header.ID() 39 } 40 41 for i := uint64(0); i < data.numBlocksToQuery; i++ { 42 block, err := r.blocks.ByID(blockID) 43 if err != nil { 44 return nil, fmt.Errorf("failed to get block by ID: %w", err) 45 } 46 result = append(result, block) 47 if block.Header.Height == 0 { 48 break 49 } 50 blockID = block.Header.ParentID 51 } 52 53 return commands.ConvertToInterfaceList(result) 54 } 55 56 // Validator validates the request. 57 // Returns admin.InvalidAdminReqError for invalid/malformed requests. 58 func (r *ReadBlocksCommand) Validator(req *admin.CommandRequest) error { 59 input, ok := req.Data.(map[string]interface{}) 60 if !ok { 61 return admin.NewInvalidAdminReqFormatError("expected map[string]any") 62 } 63 64 block, ok := input["block"] 65 if !ok { 66 return admin.NewInvalidAdminReqErrorf("the \"block\" field is required") 67 } 68 69 data := &readBlocksRequest{} 70 if blocksRequest, err := parseBlocksRequest(block); err != nil { 71 return admin.NewInvalidAdminReqErrorf("invalid 'block' field: %w", err) 72 } else { 73 data.blocksRequest = blocksRequest 74 } 75 76 if n, ok := input["n"]; ok { 77 if n, err := parseN(n); err != nil { 78 return admin.NewInvalidAdminReqErrorf("invalid 'n' field: %w", err) 79 } else { 80 data.numBlocksToQuery = n 81 } 82 } else { 83 data.numBlocksToQuery = 1 84 } 85 86 req.ValidatorData = data 87 88 return nil 89 90 } 91 92 func NewReadBlocksCommand(state protocol.State, storage storage.Blocks) commands.AdminCommand { 93 return &ReadBlocksCommand{ 94 state, 95 storage, 96 } 97 }