@@ -2,9 +2,9 @@ package launcher
22
33import (
44 "bufio"
5- "bytes"
65 "errors"
76 "fmt"
7+ "io"
88 "os"
99 "path"
1010 "path/filepath"
@@ -28,9 +28,11 @@ import (
2828 "github.com/Fantom-foundation/go-opera/gossip/emitter"
2929 "github.com/Fantom-foundation/go-opera/gossip/gasprice"
3030 "github.com/Fantom-foundation/go-opera/integration"
31- "github.com/Fantom-foundation/go-opera/integration/makegenesis "
31+ "github.com/Fantom-foundation/go-opera/integration/makefakegenesis "
3232 "github.com/Fantom-foundation/go-opera/opera"
33+ "github.com/Fantom-foundation/go-opera/opera/genesis"
3334 "github.com/Fantom-foundation/go-opera/opera/genesisstore"
35+ "github.com/Fantom-foundation/go-opera/opera/genesisstore/fileszip"
3436 futils "github.com/Fantom-foundation/go-opera/utils"
3537 "github.com/Fantom-foundation/go-opera/vecmt"
3638)
7375 Value : DefaultCacheSize ,
7476 }
7577 // GenesisFlag specifies network genesis configuration
76- GenesisFlag = cli.StringFlag {
78+ GenesisFlag = cli.StringSliceFlag {
7779 Name : "genesis" ,
78- Usage : "'path to genesis file' - sets the network genesis configuration." ,
80+ Usage : "'path to genesis file(s)' - sets the network genesis configuration." ,
81+ }
82+ ExperimentalGenesisFlag = cli.BoolFlag {
83+ Name : "genesis.allowExperimental" ,
84+ Usage : "Allow to use experimental genesis file." ,
7985 }
8086
8187 RPCGlobalGasCapFlag = cli.Uint64Flag {
@@ -95,12 +101,40 @@ var (
95101 Value : "full" ,
96102 }
97103
98- AllowedOperaGenesisHashes = map [uint64 ]hash.Hash {
99- opera .MainNetworkID : hash .HexToHash ("0x4a53c5445584b3bfc20dbfb2ec18ae20037c716f3ba2d9e1da768a9deca17cb4" ),
100- opera .TestNetworkID : hash .HexToHash ("0xc4a5fc96e575a16a9a0c7349d44dc4d0f602a54e0a8543360c2fee4c3937b49e" ),
104+ AllowedOperaGenesis = []GenesisTemplate {
105+ {
106+ Header : genesis.Header {
107+ GenesisID : hash .HexToHash ("0x4a53c5445584b3bfc20dbfb2ec18ae20037c716f3ba2d9e1da768a9deca17cb4" ),
108+ NetworkID : opera .MainNetworkID ,
109+ NetworkName : "main" ,
110+ },
111+ Hashes : genesis.Hashes {
112+ Blocks : hash.Hashes {hash .HexToHash ("0x4a53c5445584b3bfc20dbfb2ec18ae20037c716f3ba2d9e1da768a9deca17cb4" )},
113+ Epochs : hash.Hashes {hash .HexToHash ("0x4a53c5445584b3bfc20dbfb2ec18ae20037c716f3ba2d9e1da768a9deca17cb4" )},
114+ RawEvmItems : hash.Hashes {hash .HexToHash ("0x4a53c5445584b3bfc20dbfb2ec18ae20037c716f3ba2d9e1da768a9deca17cb4" )},
115+ },
116+ },
117+ {
118+ Header : genesis.Header {
119+ GenesisID : hash .HexToHash ("0xc4a5fc96e575a16a9a0c7349d44dc4d0f602a54e0a8543360c2fee4c3937b49e" ),
120+ NetworkID : opera .TestNetworkID ,
121+ NetworkName : "test" ,
122+ },
123+ Hashes : genesis.Hashes {
124+ Blocks : hash.Hashes {hash .HexToHash ("0x4a53c5445584b3bfc20dbfb2ec18ae20037c716f3ba2d9e1da768a9deca17cb4" )},
125+ Epochs : hash.Hashes {hash .HexToHash ("0x4a53c5445584b3bfc20dbfb2ec18ae20037c716f3ba2d9e1da768a9deca17cb4" )},
126+ RawEvmItems : hash.Hashes {hash .HexToHash ("0x4a53c5445584b3bfc20dbfb2ec18ae20037c716f3ba2d9e1da768a9deca17cb4" )},
127+ },
128+ },
101129 }
102130)
103131
132+ type GenesisTemplate struct {
133+ Name string
134+ Header genesis.Header
135+ Hashes genesis.Hashes
136+ }
137+
104138const (
105139 // DefaultCacheSize is calculated as memory consumption in a worst case scenario with default configuration
106140 // Average memory consumption might be 3-5 times lower than the maximum
@@ -135,12 +169,11 @@ type config struct {
135169
136170func (c * config ) AppConfigs () integration.Configs {
137171 return integration.Configs {
138- Opera : c .Opera ,
139- OperaStore : c .OperaStore ,
140- Lachesis : c .Lachesis ,
141- LachesisStore : c .LachesisStore ,
142- VectorClock : c .VectorClock ,
143- AllowedGenesis : AllowedOperaGenesisHashes ,
172+ Opera : c .Opera ,
173+ OperaStore : c .OperaStore ,
174+ Lachesis : c .Lachesis ,
175+ LachesisStore : c .LachesisStore ,
176+ VectorClock : c .VectorClock ,
144177 }
145178}
146179
@@ -164,51 +197,70 @@ func loadAllConfigs(file string, cfg *config) error {
164197 return err
165198}
166199
167- func getOperaGenesis (ctx * cli.Context ) integration.InputGenesis {
168-
169- var genesis integration.InputGenesis
200+ func getGenesisStore (ctx * cli.Context ) * genesisstore.Store {
170201 switch {
171202 case ctx .GlobalIsSet (FakeNetFlag .Name ):
172203 _ , num , err := parseFakeGen (ctx .GlobalString (FakeNetFlag .Name ))
173204 if err != nil {
174205 log .Crit ("Invalid flag" , "flag" , FakeNetFlag .Name , "err" , err )
175206 }
176- fakeGenesisStore := makegenesis .FakeGenesisStore (2 , num , futils .ToFtm (1000000000 ), futils .ToFtm (5000000 ))
177- genesis = integration.InputGenesis {
178- Hash : fakeGenesisStore .Hash (),
179- Read : func (store * genesisstore.Store ) error {
180- buf := bytes .NewBuffer (nil )
181- err = fakeGenesisStore .Export (buf )
182- if err != nil {
183- return err
184- }
185- return store .Import (buf )
186- },
187- Close : func () error {
188- return nil
189- },
190- }
207+ return makefakegenesis .FakeGenesisStore (num , futils .ToFtm (1000000000 ), futils .ToFtm (5000000 ))
191208 case ctx .GlobalIsSet (GenesisFlag .Name ):
192- genesisPath := ctx .GlobalString (GenesisFlag .Name )
209+ genesisPaths := ctx .GlobalStringSlice (GenesisFlag .Name )
210+ var files []fileszip.Reader
211+ var closers []io.Closer
193212
194- genesisFile , err := os .Open (genesisPath )
195- if err != nil {
196- utils .Fatalf ("Failed to open genesis file: %v" , err )
213+ for _ , gPath := range genesisPaths {
214+ f , err := os .Open (gPath )
215+ if err != nil {
216+ utils .Fatalf ("Failed to open genesis file: %v" , err )
217+ }
218+ fi , err := f .Stat ()
219+ if err != nil {
220+ utils .Fatalf ("Failed to stat genesis file: %v" , err )
221+ }
222+ files = append (files , fileszip.Reader {
223+ Reader : f ,
224+ Size : fi .Size (),
225+ })
226+ closers = append (closers , f )
197227 }
198- inputGenesisHash , readGenesisStore , err := genesisstore .OpenGenesisStore (genesisFile )
228+ genesisStore , genesisHashes , err := genesisstore .OpenGenesisStore (files , func () error {
229+ for _ , cl := range closers {
230+ _ = cl .Close ()
231+ }
232+ return nil
233+ })
199234 if err != nil {
200235 utils .Fatalf ("Failed to read genesis file: %v" , err )
201236 }
202237
203- genesis = integration.InputGenesis {
204- Hash : inputGenesisHash ,
205- Read : readGenesisStore ,
206- Close : genesisFile .Close ,
238+ // check if it's a trusted preset
239+ {
240+ g := genesisStore .Genesis ()
241+ gHeader := genesis.Header {
242+ GenesisID : g .GenesisID ,
243+ NetworkID : g .NetworkID ,
244+ NetworkName : g .NetworkName ,
245+ }
246+ for _ , allowed := range AllowedOperaGenesis {
247+ if allowed .Hashes .Equal (genesisHashes ) && allowed .Header .Equal (gHeader ) {
248+ log .Info ("Genesis file is a known preset" , "name" , allowed .Name )
249+ goto notExperimental
250+ }
251+ }
252+ if ctx .GlobalBool (ExperimentalGenesisFlag .Name ) {
253+ log .Warn ("Genesis file doesn't refer to any trusted preset" )
254+ } else {
255+ utils .Fatalf ("Genesis file doesn't refer to any trusted preset. Enable experimental genesis with --genesis.allowExperimental" )
256+ }
257+ notExperimental:
207258 }
259+ return genesisStore
208260 default :
209261 log .Crit ("Network genesis is not specified" )
210262 }
211- return genesis
263+ return nil
212264}
213265
214266func setBootnodes (ctx * cli.Context , urls []string , cfg * node.Config ) {
0 commit comments