github.com/prysmaticlabs/prysm@v1.4.4/tools/genesis-state-gen/main.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"encoding/hex"
     6  	"encoding/json"
     7  	"flag"
     8  	"io"
     9  	"io/ioutil"
    10  	"log"
    11  	"os"
    12  	"strings"
    13  
    14  	"github.com/ghodss/yaml"
    15  	pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
    16  	ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
    17  	"github.com/prysmaticlabs/prysm/shared/fileutil"
    18  	"github.com/prysmaticlabs/prysm/shared/interop"
    19  	"github.com/prysmaticlabs/prysm/shared/params"
    20  )
    21  
    22  // DepositDataJSON representing a json object of hex string and uint64 values for
    23  // validators on Ethereum. This file can be generated using the official eth2.0-deposit-cli.
    24  type DepositDataJSON struct {
    25  	PubKey                string `json:"pubkey"`
    26  	Amount                uint64 `json:"amount"`
    27  	WithdrawalCredentials string `json:"withdrawal_credentials"`
    28  	DepositDataRoot       string `json:"deposit_data_root"`
    29  	Signature             string `json:"signature"`
    30  }
    31  
    32  var (
    33  	depositJSONFile = flag.String(
    34  		"deposit-json-file",
    35  		"",
    36  		"Path to deposit_data.json file generated by the eth2.0-deposit-cli tool",
    37  	)
    38  	numValidators    = flag.Int("num-validators", 0, "Number of validators to deterministically generate in the generated genesis state")
    39  	useMainnetConfig = flag.Bool("mainnet-config", false, "Select whether genesis state should be generated with mainnet or minimal (default) params")
    40  	genesisTime      = flag.Uint64("genesis-time", 0, "Unix timestamp used as the genesis time in the generated genesis state (defaults to now)")
    41  	sszOutputFile    = flag.String("output-ssz", "", "Output filename of the SSZ marshaling of the generated genesis state")
    42  	yamlOutputFile   = flag.String("output-yaml", "", "Output filename of the YAML marshaling of the generated genesis state")
    43  	jsonOutputFile   = flag.String("output-json", "", "Output filename of the JSON marshaling of the generated genesis state")
    44  )
    45  
    46  func main() {
    47  	flag.Parse()
    48  	if *genesisTime == 0 {
    49  		log.Print("No --genesis-time specified, defaulting to now")
    50  	}
    51  	if *sszOutputFile == "" && *yamlOutputFile == "" && *jsonOutputFile == "" {
    52  		log.Println("Expected --output-ssz, --output-yaml, or --output-json to have been provided, received nil")
    53  		return
    54  	}
    55  	if !*useMainnetConfig {
    56  		params.OverrideBeaconConfig(params.MinimalSpecConfig())
    57  	}
    58  	var genesisState *pb.BeaconState
    59  	var err error
    60  	if *depositJSONFile != "" {
    61  		inputFile := *depositJSONFile
    62  		expanded, err := fileutil.ExpandPath(inputFile)
    63  		if err != nil {
    64  			log.Printf("Could not expand file path %s: %v", inputFile, err)
    65  			return
    66  		}
    67  		inputJSON, err := os.Open(expanded)
    68  		if err != nil {
    69  			log.Printf("Could not open JSON file for reading: %v", err)
    70  			return
    71  		}
    72  		defer func() {
    73  			if err := inputJSON.Close(); err != nil {
    74  				log.Printf("Could not close file %s: %v", inputFile, err)
    75  			}
    76  		}()
    77  		log.Printf("Generating genesis state from input JSON deposit data %s", inputFile)
    78  		genesisState, err = genesisStateFromJSONValidators(inputJSON, *genesisTime)
    79  		if err != nil {
    80  			log.Printf("Could not generate genesis beacon state: %v", err)
    81  			return
    82  		}
    83  	} else {
    84  		if *numValidators == 0 {
    85  			log.Println("Expected --num-validators to have been provided, received 0")
    86  			return
    87  		}
    88  		// If no JSON input is specified, we create the state deterministically from interop keys.
    89  		genesisState, _, err = interop.GenerateGenesisState(context.Background(), *genesisTime, uint64(*numValidators))
    90  		if err != nil {
    91  			log.Printf("Could not generate genesis beacon state: %v", err)
    92  			return
    93  		}
    94  	}
    95  
    96  	if *sszOutputFile != "" {
    97  		encodedState, err := genesisState.MarshalSSZ()
    98  		if err != nil {
    99  			log.Printf("Could not ssz marshal the genesis beacon state: %v", err)
   100  			return
   101  		}
   102  		if err := fileutil.WriteFile(*sszOutputFile, encodedState); err != nil {
   103  			log.Printf("Could not write encoded genesis beacon state to file: %v", err)
   104  			return
   105  		}
   106  		log.Printf("Done writing to %s", *sszOutputFile)
   107  	}
   108  	if *yamlOutputFile != "" {
   109  		encodedState, err := yaml.Marshal(genesisState)
   110  		if err != nil {
   111  			log.Printf("Could not yaml marshal the genesis beacon state: %v", err)
   112  			return
   113  		}
   114  		if err := fileutil.WriteFile(*yamlOutputFile, encodedState); err != nil {
   115  			log.Printf("Could not write encoded genesis beacon state to file: %v", err)
   116  			return
   117  		}
   118  		log.Printf("Done writing to %s", *yamlOutputFile)
   119  	}
   120  	if *jsonOutputFile != "" {
   121  		encodedState, err := json.Marshal(genesisState)
   122  		if err != nil {
   123  			log.Printf("Could not json marshal the genesis beacon state: %v", err)
   124  			return
   125  		}
   126  		if err := fileutil.WriteFile(*jsonOutputFile, encodedState); err != nil {
   127  			log.Printf("Could not write encoded genesis beacon state to file: %v", err)
   128  			return
   129  		}
   130  		log.Printf("Done writing to %s", *jsonOutputFile)
   131  	}
   132  }
   133  
   134  func genesisStateFromJSONValidators(r io.Reader, genesisTime uint64) (*pb.BeaconState, error) {
   135  	enc, err := ioutil.ReadAll(r)
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  	var depositJSON []*DepositDataJSON
   140  	if err := json.Unmarshal(enc, &depositJSON); err != nil {
   141  		return nil, err
   142  	}
   143  	depositDataList := make([]*ethpb.Deposit_Data, len(depositJSON))
   144  	depositDataRoots := make([][]byte, len(depositJSON))
   145  	for i, val := range depositJSON {
   146  		data, dataRootBytes, err := depositJSONToDepositData(val)
   147  		if err != nil {
   148  			return nil, err
   149  		}
   150  		depositDataList[i] = data
   151  		depositDataRoots[i] = dataRootBytes
   152  	}
   153  	beaconState, _, err := interop.GenerateGenesisStateFromDepositData(context.Background(), genesisTime, depositDataList, depositDataRoots)
   154  	if err != nil {
   155  		return nil, err
   156  	}
   157  	return beaconState, nil
   158  }
   159  
   160  func depositJSONToDepositData(input *DepositDataJSON) (depositData *ethpb.Deposit_Data, dataRoot []byte, err error) {
   161  	pubKeyBytes, err := hex.DecodeString(strings.TrimPrefix(input.PubKey, "0x"))
   162  	if err != nil {
   163  		return
   164  	}
   165  	withdrawalbytes, err := hex.DecodeString(strings.TrimPrefix(input.WithdrawalCredentials, "0x"))
   166  	if err != nil {
   167  		return
   168  	}
   169  	signatureBytes, err := hex.DecodeString(strings.TrimPrefix(input.Signature, "0x"))
   170  	if err != nil {
   171  		return
   172  	}
   173  	dataRootBytes, err := hex.DecodeString(strings.TrimPrefix(input.DepositDataRoot, "0x"))
   174  	if err != nil {
   175  		return
   176  	}
   177  	depositData = &ethpb.Deposit_Data{
   178  		PublicKey:             pubKeyBytes,
   179  		WithdrawalCredentials: withdrawalbytes,
   180  		Amount:                input.Amount,
   181  		Signature:             signatureBytes,
   182  	}
   183  	dataRoot = dataRootBytes
   184  	return
   185  }