github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/interop-cold-start/service.go (about) 1 // Package interopcoldstart allows for spinning up a deterministic 2 // local chain without the need for eth1 deposits useful for 3 // local client development and interoperability testing. 4 package interopcoldstart 5 6 import ( 7 "context" 8 "io/ioutil" 9 "math/big" 10 "time" 11 12 types "github.com/prysmaticlabs/eth2-types" 13 "github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache" 14 "github.com/prysmaticlabs/prysm/beacon-chain/db" 15 "github.com/prysmaticlabs/prysm/beacon-chain/powchain" 16 iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface" 17 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" 18 pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" 19 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 20 "github.com/prysmaticlabs/prysm/shared" 21 "github.com/prysmaticlabs/prysm/shared/interop" 22 "github.com/prysmaticlabs/prysm/shared/slotutil" 23 ) 24 25 var _ shared.Service = (*Service)(nil) 26 var _ depositcache.DepositFetcher = (*Service)(nil) 27 var _ powchain.ChainStartFetcher = (*Service)(nil) 28 29 // Service spins up an client interoperability service that handles responsibilities such 30 // as kickstarting a genesis state for the beacon node from cli flags or a genesis.ssz file. 31 type Service struct { 32 cfg *Config 33 ctx context.Context 34 cancel context.CancelFunc 35 chainStartDeposits []*ethpb.Deposit 36 } 37 38 // Config options for the interop service. 39 type Config struct { 40 GenesisTime uint64 41 NumValidators uint64 42 BeaconDB db.HeadAccessDatabase 43 DepositCache *depositcache.DepositCache 44 GenesisPath string 45 } 46 47 // NewService is an interoperability testing service to inject a deterministically generated genesis state 48 // into the beacon chain database and running services at start up. This service should not be used in production 49 // as it does not have any value other than ease of use for testing purposes. 50 func NewService(ctx context.Context, cfg *Config) *Service { 51 log.Warn("Saving generated genesis state in database for interop testing") 52 ctx, cancel := context.WithCancel(ctx) 53 54 s := &Service{ 55 cfg: cfg, 56 ctx: ctx, 57 cancel: cancel, 58 } 59 60 if s.cfg.GenesisPath != "" { 61 data, err := ioutil.ReadFile(s.cfg.GenesisPath) 62 if err != nil { 63 log.Fatalf("Could not read pre-loaded state: %v", err) 64 } 65 genesisState := &pb.BeaconState{} 66 if err := genesisState.UnmarshalSSZ(data); err != nil { 67 log.Fatalf("Could not unmarshal pre-loaded state: %v", err) 68 } 69 genesisTrie, err := v1.InitializeFromProto(genesisState) 70 if err != nil { 71 log.Fatalf("Could not get state trie: %v", err) 72 } 73 if err := s.saveGenesisState(ctx, genesisTrie); err != nil { 74 log.Fatalf("Could not save interop genesis state %v", err) 75 } 76 return s 77 } 78 79 // Save genesis state in db 80 genesisState, _, err := interop.GenerateGenesisState(ctx, s.cfg.GenesisTime, s.cfg.NumValidators) 81 if err != nil { 82 log.Fatalf("Could not generate interop genesis state: %v", err) 83 } 84 genesisTrie, err := v1.InitializeFromProto(genesisState) 85 if err != nil { 86 log.Fatalf("Could not get state trie: %v", err) 87 } 88 if s.cfg.GenesisTime == 0 { 89 // Generated genesis time; fetch it 90 s.cfg.GenesisTime = genesisTrie.GenesisTime() 91 } 92 gRoot, err := genesisTrie.HashTreeRoot(s.ctx) 93 if err != nil { 94 log.Fatalf("Could not hash tree root genesis state: %v", err) 95 } 96 go slotutil.CountdownToGenesis(ctx, time.Unix(int64(s.cfg.GenesisTime), 0), s.cfg.NumValidators, gRoot) 97 98 if err := s.saveGenesisState(ctx, genesisTrie); err != nil { 99 log.Fatalf("Could not save interop genesis state %v", err) 100 } 101 102 return s 103 } 104 105 // Start initializes the genesis state from configured flags. 106 func (s *Service) Start() { 107 } 108 109 // Stop does nothing. 110 func (s *Service) Stop() error { 111 return nil 112 } 113 114 // Status always returns nil. 115 func (s *Service) Status() error { 116 return nil 117 } 118 119 // AllDeposits mocks out the deposit cache functionality for interop. 120 func (s *Service) AllDeposits(_ context.Context, _ *big.Int) []*ethpb.Deposit { 121 return []*ethpb.Deposit{} 122 } 123 124 // ChainStartDeposits mocks out the powchain functionality for interop. 125 func (s *Service) ChainStartDeposits() []*ethpb.Deposit { 126 return s.chainStartDeposits 127 } 128 129 // ChainStartEth1Data mocks out the powchain functionality for interop. 130 func (s *Service) ChainStartEth1Data() *ethpb.Eth1Data { 131 return ðpb.Eth1Data{} 132 } 133 134 // PreGenesisState returns an empty beacon state. 135 func (s *Service) PreGenesisState() iface.BeaconState { 136 return &v1.BeaconState{} 137 } 138 139 // ClearPreGenesisData -- 140 func (s *Service) ClearPreGenesisData() { 141 // no-op 142 } 143 144 // DepositByPubkey mocks out the deposit cache functionality for interop. 145 func (s *Service) DepositByPubkey(_ context.Context, _ []byte) (*ethpb.Deposit, *big.Int) { 146 return ðpb.Deposit{}, nil 147 } 148 149 // DepositsNumberAndRootAtHeight mocks out the deposit cache functionality for interop. 150 func (s *Service) DepositsNumberAndRootAtHeight(_ context.Context, _ *big.Int) (uint64, [32]byte) { 151 return 0, [32]byte{} 152 } 153 154 // FinalizedDeposits mocks out the deposit cache functionality for interop. 155 func (s *Service) FinalizedDeposits(_ context.Context) *depositcache.FinalizedDeposits { 156 return nil 157 } 158 159 // NonFinalizedDeposits mocks out the deposit cache functionality for interop. 160 func (s *Service) NonFinalizedDeposits(_ context.Context, _ *big.Int) []*ethpb.Deposit { 161 return []*ethpb.Deposit{} 162 } 163 164 func (s *Service) saveGenesisState(ctx context.Context, genesisState iface.BeaconState) error { 165 if err := s.cfg.BeaconDB.SaveGenesisData(ctx, genesisState); err != nil { 166 return err 167 } 168 169 s.chainStartDeposits = make([]*ethpb.Deposit, genesisState.NumValidators()) 170 171 for i := types.ValidatorIndex(0); uint64(i) < uint64(genesisState.NumValidators()); i++ { 172 pk := genesisState.PubkeyAtIndex(i) 173 s.chainStartDeposits[i] = ðpb.Deposit{ 174 Data: ðpb.Deposit_Data{ 175 PublicKey: pk[:], 176 }, 177 } 178 } 179 return nil 180 }