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

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"flag"
     6  	"io/ioutil"
     7  	"log"
     8  	"os"
     9  	"path"
    10  
    11  	"github.com/pkg/errors"
    12  	types "github.com/prysmaticlabs/eth2-types"
    13  	"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
    14  	"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
    15  	iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
    16  	"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
    17  	pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
    18  	ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
    19  	"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
    20  	"github.com/prysmaticlabs/prysm/shared/benchutil"
    21  	"github.com/prysmaticlabs/prysm/shared/fileutil"
    22  	"github.com/prysmaticlabs/prysm/shared/interop"
    23  	"github.com/prysmaticlabs/prysm/shared/params"
    24  	"github.com/prysmaticlabs/prysm/shared/testutil"
    25  )
    26  
    27  var (
    28  	outputDir = flag.String("output-dir", "", "Directory to write SSZ files to")
    29  	overwrite = flag.Bool("overwrite", false, "If SSZ files exist in the output directory, they will be overwritten")
    30  )
    31  
    32  func main() {
    33  	flag.Parse()
    34  	if *outputDir == "" {
    35  		log.Fatal("Please specify --output-dir to write SSZ files to")
    36  	}
    37  
    38  	if !*overwrite {
    39  		if _, err := os.Stat(path.Join(*outputDir, benchutil.BState1EpochFileName)); err == nil {
    40  			log.Fatal("The file exists. Use a different file name or the --overwrite flag")
    41  		}
    42  		if _, err := os.Stat(path.Join(*outputDir, benchutil.BState2EpochFileName)); err == nil {
    43  			log.Fatal("The file exists. Use a different file name or the --overwrite flag")
    44  		}
    45  		if _, err := os.Stat(path.Join(*outputDir, benchutil.FullBlockFileName)); err == nil {
    46  			log.Fatal("The file exists. Use a different file name or the --overwrite flag")
    47  		}
    48  	}
    49  
    50  	if err := fileutil.MkdirAll(*outputDir); err != nil {
    51  		log.Fatal(err)
    52  	}
    53  
    54  	log.Printf("Output dir is: %s", *outputDir)
    55  	log.Println("Generating genesis state")
    56  	// Generating this for the 2 following states.
    57  	if err := generateGenesisBeaconState(); err != nil {
    58  		log.Fatalf("Could not generate genesis state: %v", err)
    59  	}
    60  	log.Println("Generating full block and state after 1 skipped epoch")
    61  	if err := generateMarshalledFullStateAndBlock(); err != nil {
    62  		log.Fatalf("Could not generate full state and block: %v", err)
    63  	}
    64  	log.Println("Generating state after 2 fully attested epochs")
    65  	if err := generate2FullEpochState(); err != nil {
    66  		log.Fatalf("Could not generate 2 full epoch state: %v", err)
    67  	}
    68  	// Removing the genesis state SSZ since its 10MB large and no longer needed.
    69  	if err := os.Remove(path.Join(*outputDir, benchutil.GenesisFileName)); err != nil {
    70  		log.Fatal(err)
    71  	}
    72  }
    73  
    74  func generateGenesisBeaconState() error {
    75  	genesisState, _, err := interop.GenerateGenesisState(context.Background(), 0, benchutil.ValidatorCount)
    76  	if err != nil {
    77  		return err
    78  	}
    79  	beaconBytes, err := genesisState.MarshalSSZ()
    80  	if err != nil {
    81  		return err
    82  	}
    83  	return fileutil.WriteFile(path.Join(*outputDir, benchutil.GenesisFileName), beaconBytes)
    84  }
    85  
    86  func generateMarshalledFullStateAndBlock() error {
    87  	benchutil.SetBenchmarkConfig()
    88  	beaconState, err := genesisBeaconState()
    89  	if err != nil {
    90  		return err
    91  	}
    92  
    93  	privs, _, err := interop.DeterministicallyGenerateKeys(0, benchutil.ValidatorCount)
    94  	if err != nil {
    95  		return err
    96  	}
    97  
    98  	conf := &testutil.BlockGenConfig{}
    99  	slotsPerEpoch := params.BeaconConfig().SlotsPerEpoch
   100  	// Small offset for the beacon state so we dont process a block on an epoch.
   101  	slotOffset := types.Slot(2)
   102  	block, err := testutil.GenerateFullBlock(beaconState, privs, conf, slotsPerEpoch+slotOffset)
   103  	if err != nil {
   104  		return err
   105  	}
   106  	beaconState, err = state.ExecuteStateTransition(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(block))
   107  	if err != nil {
   108  		return err
   109  	}
   110  
   111  	attConfig := &testutil.BlockGenConfig{
   112  		NumAttestations: benchutil.AttestationsPerEpoch / uint64(slotsPerEpoch),
   113  	}
   114  
   115  	var atts []*ethpb.Attestation
   116  	for i := slotOffset + 1; i < slotsPerEpoch+slotOffset; i++ {
   117  		attsForSlot, err := testutil.GenerateAttestations(beaconState, privs, attConfig.NumAttestations, i, false)
   118  		if err != nil {
   119  			return err
   120  		}
   121  		atts = append(atts, attsForSlot...)
   122  	}
   123  
   124  	block, err = testutil.GenerateFullBlock(beaconState, privs, attConfig, beaconState.Slot())
   125  	if err != nil {
   126  		return errors.Wrap(err, "could not generate full block")
   127  	}
   128  	block.Block.Body.Attestations = append(atts, block.Block.Body.Attestations...)
   129  
   130  	s, err := state.CalculateStateRoot(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(block))
   131  	if err != nil {
   132  		return errors.Wrap(err, "could not calculate state root")
   133  	}
   134  	block.Block.StateRoot = s[:]
   135  	// Temporarily incrementing the beacon state slot here since BeaconProposerIndex is a
   136  	// function deterministic on beacon state slot.
   137  	if err := beaconState.SetSlot(beaconState.Slot() + 1); err != nil {
   138  		return err
   139  	}
   140  	proposerIdx, err := helpers.BeaconProposerIndex(beaconState)
   141  	if err != nil {
   142  		return err
   143  	}
   144  	block.Signature, err = helpers.ComputeDomainAndSign(beaconState, helpers.CurrentEpoch(beaconState), block.Block, params.BeaconConfig().DomainBeaconProposer, privs[proposerIdx])
   145  	if err != nil {
   146  		return err
   147  	}
   148  	if err := beaconState.SetSlot(beaconState.Slot() - 1); err != nil {
   149  		return err
   150  	}
   151  
   152  	beaconBytes, err := beaconState.MarshalSSZ()
   153  	if err != nil {
   154  		return err
   155  	}
   156  	if err := fileutil.WriteFile(path.Join(*outputDir, benchutil.BState1EpochFileName), beaconBytes); err != nil {
   157  		return err
   158  	}
   159  
   160  	// Running a single state transition to make sure the generated files aren't broken.
   161  	_, err = state.ExecuteStateTransition(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(block))
   162  	if err != nil {
   163  		return err
   164  	}
   165  
   166  	blockBytes, err := block.MarshalSSZ()
   167  	if err != nil {
   168  		return err
   169  	}
   170  
   171  	return fileutil.WriteFile(path.Join(*outputDir, benchutil.FullBlockFileName), blockBytes)
   172  }
   173  
   174  func generate2FullEpochState() error {
   175  	benchutil.SetBenchmarkConfig()
   176  	beaconState, err := genesisBeaconState()
   177  	if err != nil {
   178  		return err
   179  	}
   180  
   181  	privs, _, err := interop.DeterministicallyGenerateKeys(0, benchutil.ValidatorCount)
   182  	if err != nil {
   183  		return err
   184  	}
   185  
   186  	attConfig := &testutil.BlockGenConfig{
   187  		NumAttestations: benchutil.AttestationsPerEpoch / uint64(params.BeaconConfig().SlotsPerEpoch),
   188  	}
   189  
   190  	for i := types.Slot(0); i < params.BeaconConfig().SlotsPerEpoch*2-1; i++ {
   191  		block, err := testutil.GenerateFullBlock(beaconState, privs, attConfig, beaconState.Slot())
   192  		if err != nil {
   193  			return err
   194  		}
   195  		beaconState, err = state.ExecuteStateTransition(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(block))
   196  		if err != nil {
   197  			return err
   198  		}
   199  	}
   200  
   201  	beaconBytes, err := beaconState.MarshalSSZ()
   202  	if err != nil {
   203  		return err
   204  	}
   205  
   206  	return fileutil.WriteFile(path.Join(*outputDir, benchutil.BState2EpochFileName), beaconBytes)
   207  }
   208  
   209  func genesisBeaconState() (iface.BeaconState, error) {
   210  	beaconBytes, err := ioutil.ReadFile(path.Join(*outputDir, benchutil.GenesisFileName))
   211  	if err != nil {
   212  		return nil, errors.Wrap(err, "cannot read genesis state file")
   213  	}
   214  	genesisState := &pb.BeaconState{}
   215  	if err := genesisState.UnmarshalSSZ(beaconBytes); err != nil {
   216  		return nil, errors.Wrap(err, "cannot unmarshal genesis state file")
   217  	}
   218  	return v1.InitializeFromProtoUnsafe(genesisState)
   219  }