github.com/koko1123/flow-go-1@v0.29.6/admin/commands/storage/helper.go (about) 1 package storage 2 3 import ( 4 "fmt" 5 "math" 6 "strings" 7 8 "github.com/koko1123/flow-go-1/model/flow" 9 "github.com/koko1123/flow-go-1/state/protocol" 10 ) 11 12 type blocksRequestType int 13 14 const ( 15 blocksRequestByID blocksRequestType = iota 16 blocksRequestByHeight 17 blocksRequestFinal 18 blocksRequestSealed 19 ) 20 21 const ( 22 FINAL = "final" 23 SEALED = "sealed" 24 ) 25 26 type blocksRequest struct { 27 requestType blocksRequestType 28 value interface{} 29 } 30 31 // parseN verifies that the input is an integral float64 value >=1. 32 // All generic errors indicate a benign validation failure, and should be wrapped by the caller. 33 func parseN(m interface{}) (uint64, error) { 34 n, ok := m.(float64) 35 if !ok { 36 return 0, fmt.Errorf("invalid value for \"n\": %v", n) 37 } 38 if math.Trunc(n) != n { 39 return 0, fmt.Errorf("\"n\" must be an integer, got: %v", n) 40 } 41 if n < 1 { 42 return 0, fmt.Errorf("\"n\" must be at least 1, got: %v", n) 43 } 44 return uint64(n), nil 45 } 46 47 // parseBlocksRequest parses the block field of an admin request. 48 // All generic errors indicate a benign validation failure, and should be wrapped by the caller. 49 func parseBlocksRequest(block interface{}) (*blocksRequest, error) { 50 errInvalidBlockValue := fmt.Errorf("invalid value for \"block\": expected %q, %q, block ID, or block height, but got: %v", FINAL, SEALED, block) 51 req := &blocksRequest{} 52 53 switch block := block.(type) { 54 case string: 55 block = strings.ToLower(strings.TrimSpace(block)) 56 if block == FINAL { 57 req.requestType = blocksRequestFinal 58 } else if block == SEALED { 59 req.requestType = blocksRequestSealed 60 } else if id, err := flow.HexStringToIdentifier(block); err == nil { 61 req.requestType = blocksRequestByID 62 req.value = id 63 } else { 64 return nil, errInvalidBlockValue 65 } 66 case float64: 67 if block < 0 || math.Trunc(block) != block { 68 return nil, errInvalidBlockValue 69 } 70 req.requestType = blocksRequestByHeight 71 req.value = uint64(block) 72 default: 73 return nil, errInvalidBlockValue 74 } 75 76 return req, nil 77 } 78 79 func getBlockHeader(state protocol.State, req *blocksRequest) (*flow.Header, error) { 80 switch req.requestType { 81 case blocksRequestByID: 82 return state.AtBlockID(req.value.(flow.Identifier)).Head() 83 case blocksRequestByHeight: 84 return state.AtHeight(req.value.(uint64)).Head() 85 case blocksRequestFinal: 86 return state.Final().Head() 87 case blocksRequestSealed: 88 return state.Sealed().Head() 89 default: 90 return nil, fmt.Errorf("invalid request type: %v", req.requestType) 91 } 92 }