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 = ðpb.Deposit_Data{ 178 PublicKey: pubKeyBytes, 179 WithdrawalCredentials: withdrawalbytes, 180 Amount: input.Amount, 181 Signature: signatureBytes, 182 } 183 dataRoot = dataRootBytes 184 return 185 }