code.vegaprotocol.io/vega@v0.79.0/vegatools/checkpoint/parse.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package checkpoint
    17  
    18  import (
    19  	"errors"
    20  	"fmt"
    21  	"log"
    22  	"os"
    23  
    24  	"code.vegaprotocol.io/vega/libs/proto"
    25  	checkpoint "code.vegaprotocol.io/vega/protos/vega/checkpoint/v1"
    26  
    27  	"google.golang.org/protobuf/reflect/protoreflect"
    28  )
    29  
    30  var (
    31  	// ErrCheckpointFileEmpty obviously means the checkpoint file was empty.
    32  	ErrCheckpointFileEmpty = errors.New("given checkpoint file is empty or unreadable")
    33  	// ErrMissingOutFile no output file name argument provided.
    34  	ErrMissingOutFile = errors.New("output file not specified")
    35  )
    36  
    37  // Run ... the main entry point of the command.
    38  func Run(inFile, outFile string, generate, validate, dummy bool) error {
    39  	if generate && outFile == "" {
    40  		fmt.Println("No output file specified")
    41  		return ErrMissingOutFile
    42  	}
    43  	// generate some files to play with
    44  	if dummy {
    45  		return generateDummy(inFile, outFile)
    46  	}
    47  
    48  	data, err := os.ReadFile(inFile)
    49  	if err != nil {
    50  		return err
    51  	}
    52  
    53  	fmt.Printf("Read %d bytes from %s\n", len(data), inFile)
    54  
    55  	if len(data) == 0 {
    56  		return ErrCheckpointFileEmpty
    57  	}
    58  
    59  	if generate {
    60  		return generateCheckpoint(data, outFile)
    61  	}
    62  
    63  	cp := &checkpoint.Checkpoint{}
    64  	if err = proto.Unmarshal(data, cp); err != nil {
    65  		return err
    66  	}
    67  
    68  	parsed, err := unmarshalAll(cp)
    69  	if err != nil {
    70  		return err
    71  	}
    72  	// print output at the end
    73  	defer func() {
    74  		printParsed(parsed, err != nil)
    75  	}()
    76  
    77  	if validate {
    78  		if err = parsed.CheckAssetsCollateral(); err != nil {
    79  			return err
    80  		}
    81  	}
    82  
    83  	return writeOut(parsed, outFile)
    84  }
    85  
    86  func generateDummy(cpF, jsonFName string) error {
    87  	d := dummy()
    88  
    89  	cp, h, err := d.CheckpointData() // get the data as checkpoint
    90  	if err != nil {
    91  		log.Printf("Could not convert dummy to checkpoint data to write to file: %+v\n", err)
    92  		return err
    93  	}
    94  
    95  	if err = writeCheckpoint(cp, h, cpF); err != nil {
    96  		log.Printf("Error writing checkpoint data to file '%s': %+v\n", cpF, err)
    97  		return err
    98  	}
    99  
   100  	if err = writeOut(d, jsonFName); err != nil {
   101  		log.Printf("Error writing JSON file '%s' from dummy: %+v\n", jsonFName, err)
   102  		return err
   103  	}
   104  	return nil
   105  }
   106  
   107  func generateCheckpoint(data []byte, outF string) error {
   108  	of, err := os.Create(outF)
   109  	if err != nil {
   110  		log.Printf("Failed to create output file %s: %+v\n", outF, err)
   111  		return err
   112  	}
   113  
   114  	defer func() { _ = of.Close() }()
   115  
   116  	a, err := fromJSON(data)
   117  	if err != nil {
   118  		log.Printf("Could not unmarshal input: %+v\n", err)
   119  		return err
   120  	}
   121  
   122  	out, h, err := a.CheckpointData()
   123  	if err != nil {
   124  		log.Printf("Could not generate checkpoint data: %+v\n", err)
   125  		return err
   126  	}
   127  
   128  	n, err := of.Write(out)
   129  	if err != nil {
   130  		log.Printf("Failed to write output to file: %+v\n", err)
   131  		return err
   132  	}
   133  
   134  	fmt.Printf("Successfully wrote %d bytes to file %s\n", n, outF)
   135  	fmt.Printf("hash for checkpoint is %s\n", h)
   136  	return nil
   137  }
   138  
   139  func writeCheckpoint(data []byte, h string, outF string) error {
   140  	of, err := os.Create(outF)
   141  	if err != nil {
   142  		fmt.Printf("Failed to create output file %s: %+v\n", outF, err)
   143  		return err
   144  	}
   145  
   146  	defer func() { _ = of.Close() }()
   147  
   148  	n, err := of.Write(data)
   149  	if err != nil {
   150  		fmt.Printf("Failed to write output to file '%s': %+v\n", outF, err)
   151  		return err
   152  	}
   153  
   154  	fmt.Printf("Successfully wrote %d bytes to file %s\n", n, outF)
   155  	fmt.Printf("Checkpoint hash is %s\n", h)
   156  	return nil
   157  }
   158  
   159  func printParsed(a *all, isErr bool) {
   160  	data, err := a.JSON()
   161  	if err != nil {
   162  		log.Printf("Failed to marshal data to JSON: %+v\n", err)
   163  		return
   164  	}
   165  
   166  	if isErr {
   167  		if _, err = os.Stderr.WriteString(string(data)); err == nil {
   168  			return
   169  		}
   170  		fmt.Printf("Could not write to stderr: %+v\n", err)
   171  	}
   172  
   173  	fmt.Printf("Output:\n%s\n", string(data))
   174  }
   175  
   176  func writeOut(a *all, path string) error {
   177  	if path == "" {
   178  		return nil
   179  	}
   180  
   181  	data, err := a.JSON()
   182  	if err != nil {
   183  		return err
   184  	}
   185  
   186  	f, err := os.Create(path)
   187  	if err != nil {
   188  		return err
   189  	}
   190  
   191  	defer func() { _ = f.Close() }()
   192  
   193  	n, err := f.Write(data)
   194  	if err != nil {
   195  		return err
   196  	}
   197  
   198  	fmt.Printf("Wrote %d bytes to %s\n", n, path)
   199  	return nil
   200  }
   201  
   202  func unmarshalAll(cp *checkpoint.Checkpoint) (ret *all, err error) {
   203  	ret = newAll()
   204  
   205  	cp.ProtoReflect().Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
   206  		name := string(fd.Name())
   207  		msg, ok := ret.messages[name]
   208  		if ok {
   209  			if err = proto.Unmarshal(v.Bytes(), msg); err != nil {
   210  				return false
   211  			}
   212  		}
   213  		return true
   214  	})
   215  
   216  	return ret, err
   217  }