github.com/streamingfast/substreams@v1.6.2/info/info.go (about) 1 package info 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/streamingfast/substreams/manifest" 8 pbsubstreams "github.com/streamingfast/substreams/pb/sf/substreams/v1" 9 "github.com/streamingfast/substreams/pipeline/exec" 10 "google.golang.org/protobuf/types/descriptorpb" 11 ) 12 13 type BasicInfo struct { 14 Name string `json:"name"` 15 Version string `json:"version"` 16 Documentation *string `json:"documentation,omitempty"` 17 Network string `json:"network,omitempty"` 18 Image []byte `json:"-"` 19 Modules []ModulesInfo `json:"modules"` 20 SinkInfo *SinkInfo `json:"sink_info,omitempty"` 21 ProtoPackages []string `json:"proto_packages"` // list of proto packages 22 Networks map[string]*manifest.NetworkParams `json:"networks,omitempty"` 23 ProtoSourceCode map[string][]*SourceCodeInfo `json:"proto_source_code"` // map of proto file name to .proto file contents 24 ProtoMessagesByPackage map[string][]*ProtoMessageInfo `json:"proto_messages_by_package"` // map of package name to a list of messages info in that package 25 } 26 27 type SourceCodeInfo struct { 28 Filename string `json:"filename"` 29 Source string `json:"source"` 30 } 31 32 type ProtoMessageInfo struct { 33 Name string `json:"name"` 34 Package string `json:"package"` 35 Type string `json:"type"` 36 File string `json:"file"` 37 Proto string `json:"proto"` 38 Documentation string `json:"documentation"` 39 NestedMessages []*ProtoMessageInfo `json:"nested_messages"` 40 } 41 42 type SinkInfo struct { 43 Configs string `json:"desc"` 44 TypeUrl string `json:"type_url"` 45 Files map[string][]byte `json:"files"` 46 } 47 48 type ExtendedInfo struct { 49 *BasicInfo 50 51 ExecutionStages [][][]string `json:"execution_stages,omitempty"` 52 } 53 54 type ProtoFileInfo struct { 55 Name *string `json:"name,omitempty"` 56 Package *string `json:"package,omitempty"` 57 Dependencies []string `json:"dependencies,omitempty"` 58 PublicDependencies []int32 `json:"public_dependencies,omitempty"` 59 MessageType []*descriptorpb.DescriptorProto `json:"message_type,omitempty"` 60 Services []*descriptorpb.ServiceDescriptorProto `json:"services,omitempty"` 61 } 62 63 type ModulesInfo struct { 64 Name string `json:"name"` 65 Kind string `json:"kind"` 66 Inputs []ModuleInput `json:"inputs"` 67 OutputType *string `json:"output_type,omitempty"` //for map inputs 68 ValueType *string `json:"value_type,omitempty"` //for store inputs 69 UpdatePolicy *string `json:"update_policy,omitempty"` //for store inputs 70 BlockFilter *pbsubstreams.Module_BlockFilter `json:"block_filter,omitempty"` 71 InitialBlock uint64 `json:"initial_block"` 72 Documentation *string `json:"documentation,omitempty"` 73 Hash string `json:"hash"` 74 } 75 76 type ModuleInput struct { 77 Type string `json:"type"` 78 Name string `json:"name"` 79 Mode *string `json:"mode,omitempty"` //for store inputs 80 } 81 82 func Basic(pkg *pbsubstreams.Package, graph *manifest.ModuleGraph) (*BasicInfo, error) { 83 name := "Unnamed" 84 var doc, version string 85 if len(pkg.PackageMeta) != 0 { 86 name = pkg.PackageMeta[0].Name 87 version = pkg.PackageMeta[0].Version 88 doc = pkg.PackageMeta[0].Doc 89 } 90 91 manifestInfo := &BasicInfo{ 92 Name: name, 93 Network: pkg.Network, 94 Version: version, 95 Image: pkg.Image, 96 } 97 98 if pkg.Networks != nil { 99 manifestInfo.Networks = make(map[string]*manifest.NetworkParams) 100 } 101 for k, v := range pkg.Networks { 102 params := &manifest.NetworkParams{} 103 104 if v.InitialBlocks != nil { 105 params.InitialBlocks = make(map[string]uint64) 106 } 107 for kk, vv := range v.InitialBlocks { 108 params.InitialBlocks[kk] = vv 109 } 110 111 if v.Params != nil { 112 params.Params = make(map[string]string) 113 } 114 for kk, vv := range v.Params { 115 params.Params[kk] = vv 116 } 117 manifestInfo.Networks[k] = params 118 } 119 120 if doc != "" { 121 manifestInfo.Documentation = strPtr(strings.Replace(doc, "\n", "\n ", -1)) 122 } 123 124 modules := make([]ModulesInfo, 0, len(pkg.Modules.Modules)) 125 126 hashes := manifest.NewModuleHashes() 127 for ix, mod := range pkg.Modules.Modules { 128 modInfo := ModulesInfo{} 129 130 _, _ = hashes.HashModule(pkg.Modules, mod, graph) 131 modInfo.Hash = hashes.Get(mod.Name) 132 133 modInfo.Name = mod.Name 134 modInfo.InitialBlock = mod.InitialBlock 135 136 kind := mod.GetKind() 137 switch v := kind.(type) { 138 139 case *pbsubstreams.Module_KindBlockIndex_: 140 modInfo.Kind = "index" 141 modInfo.OutputType = strPtr(v.KindBlockIndex.OutputType) 142 case *pbsubstreams.Module_KindMap_: 143 modInfo.Kind = "map" 144 modInfo.OutputType = strPtr(v.KindMap.OutputType) 145 case *pbsubstreams.Module_KindStore_: 146 modInfo.Kind = "store" 147 modInfo.ValueType = strPtr(v.KindStore.ValueType) 148 modInfo.UpdatePolicy = strPtr(v.KindStore.UpdatePolicy.Pretty()) 149 default: 150 modInfo.Kind = "unknown" 151 } 152 153 if pkg.ModuleMeta != nil { 154 modMeta := pkg.ModuleMeta[ix] 155 if modMeta != nil && modMeta.Doc != "" { 156 modInfo.Documentation = strPtr(strings.Replace(modMeta.Doc, "\n", "\n ", -1)) 157 } 158 } 159 160 inputs := make([]ModuleInput, 0, len(mod.Inputs)) 161 for _, input := range mod.Inputs { 162 inputInfo := ModuleInput{} 163 164 switch v := input.Input.(type) { 165 case *pbsubstreams.Module_Input_Source_: 166 inputInfo.Type = "source" 167 inputInfo.Name = v.Source.Type 168 case *pbsubstreams.Module_Input_Map_: 169 inputInfo.Type = "map" 170 inputInfo.Name = v.Map.ModuleName 171 case *pbsubstreams.Module_Input_Store_: 172 inputInfo.Type = "store" 173 inputInfo.Name = v.Store.ModuleName 174 if v.Store.Mode > 0 { 175 inputInfo.Mode = strPtr(v.Store.Mode.Pretty()) 176 } 177 case *pbsubstreams.Module_Input_Params_: 178 inputInfo.Type = "params" 179 inputInfo.Name = input.GetParams().Value 180 default: 181 inputInfo.Type = "unknown" 182 inputInfo.Name = "unknown" 183 } 184 185 inputs = append(inputs, inputInfo) 186 } 187 modInfo.Inputs = inputs 188 modInfo.BlockFilter = mod.BlockFilter 189 190 modules = append(modules, modInfo) 191 } 192 manifestInfo.Modules = modules 193 194 protoPackageParser, err := NewProtoPackageParser(pkg.ProtoFiles) 195 if err != nil { 196 return nil, fmt.Errorf("proto package parser: %w", err) 197 } 198 packageMessageMap, err := protoPackageParser.Parse() 199 if err != nil { 200 return nil, fmt.Errorf("parse proto files: %w", err) 201 } 202 manifestInfo.ProtoMessagesByPackage = packageMessageMap 203 204 manifestInfo.ProtoPackages = protoPackageParser.GetPackagesList() 205 manifestInfo.ProtoSourceCode = protoPackageParser.GetFilesSourceCode() 206 207 if pkg.SinkConfig != nil { 208 desc, files, err := manifest.DescribeSinkConfigs(pkg) 209 if err != nil { 210 return nil, fmt.Errorf("describe sink configs: %w", err) 211 } 212 manifestInfo.SinkInfo = &SinkInfo{ 213 Configs: desc, 214 TypeUrl: pkg.SinkConfig.TypeUrl, 215 Files: files, 216 } 217 } 218 219 return manifestInfo, nil 220 } 221 222 func Extended(manifestPath string, outputModule string, skipValidation bool) (*ExtendedInfo, error) { 223 var opts []manifest.Option 224 if skipValidation { 225 opts = append(opts, manifest.SkipPackageValidationReader()) 226 } 227 reader, err := manifest.NewReader(manifestPath, opts...) 228 if err != nil { 229 return nil, fmt.Errorf("manifest reader: %w", err) 230 } 231 232 pkg, graph, err := reader.Read() 233 if err != nil { 234 return nil, fmt.Errorf("read manifest %q: %w", manifestPath, err) 235 } 236 237 return ExtendedWithPackage(pkg, graph, outputModule) 238 } 239 240 func ExtendedWithPackage(pkg *pbsubstreams.Package, graph *manifest.ModuleGraph, outputModule string) (*ExtendedInfo, error) { 241 basicInfo, err := Basic(pkg, graph) 242 if err != nil { 243 return nil, err 244 } 245 246 var stages [][][]string 247 if outputModule != "" { 248 execGraph, err := exec.NewOutputModuleGraph(outputModule, true, pkg.Modules) 249 if err != nil { 250 return nil, fmt.Errorf("creating output module graph: %w", err) 251 } 252 stages = make([][][]string, 0, len(execGraph.StagedUsedModules())) 253 for _, layers := range execGraph.StagedUsedModules() { 254 var layerDefs [][]string 255 for _, l := range layers { 256 var mods []string 257 for _, m := range l { 258 mods = append(mods, m.Name) 259 } 260 layerDefs = append(layerDefs, mods) 261 } 262 stages = append(stages, layerDefs) 263 } 264 } 265 266 return &ExtendedInfo{ 267 BasicInfo: basicInfo, 268 ExecutionStages: stages, 269 }, nil 270 } 271 272 func strPtr(s string) *string { 273 return &s 274 }