github.com/koko1123/flow-go-1@v0.29.6/admin/commands/storage/read_blocks.go (about)

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