@@ -21,6 +21,7 @@ import (
2121 "fmt"
2222 "io"
2323 "os"
24+ "reflect"
2425 "runtime"
2526 "strconv"
2627 "sync/atomic"
@@ -56,6 +57,20 @@ The init command initializes a new genesis block and definition for the network.
5657This is a destructive action and changes the network in which you will be
5758participating.
5859
60+ It expects the genesis file as argument.` ,
61+ }
62+ updateCommand = cli.Command {
63+ Action : utils .MigrateFlags (updateTransitions ),
64+ Name : "update" ,
65+ Usage : "Update genesis block with new transitions" ,
66+ ArgsUsage : "<genesisPath>" ,
67+ Flags : []cli.Flag {
68+ utils .DataDirFlag ,
69+ },
70+ Category : "BLOCKCHAIN COMMANDS" ,
71+ Description : `
72+ The update commands updates the chain data configuration in genesis block for new transition changes.
73+
5974It expects the genesis file as argument.` ,
6075 }
6176 dumpGenesisCommand = cli.Command {
@@ -206,6 +221,64 @@ func getIsQuorum(file io.Reader) bool {
206221 return altGenesis .Config .IsQuorum == nil || * altGenesis .Config .IsQuorum
207222}
208223
224+ // updateTransitions will update genesis block with the new transitions data
225+ func updateTransitions (ctx * cli.Context ) error {
226+ // Open and initialise both full and light databases
227+ stack , _ := makeConfigNode (ctx )
228+ defer stack .Close ()
229+
230+ // Make sure we have a valid genesis JSON
231+ genesisPath := ctx .Args ().First ()
232+ if len (genesisPath ) == 0 {
233+ utils .Fatalf ("Must supply path to genesis JSON file" )
234+ }
235+ file , err := os .Open (genesisPath )
236+ if err != nil {
237+ utils .Fatalf ("Failed to read genesis file: %v" , err )
238+ }
239+ defer file .Close ()
240+
241+ genesis := new (core.Genesis )
242+ if err := json .NewDecoder (file ).Decode (genesis ); err != nil {
243+ utils .Fatalf ("invalid genesis file: %v" , err )
244+ }
245+
246+ // Quorum
247+ file .Seek (0 , 0 )
248+ genesis .Config .IsQuorum = getIsQuorum (file )
249+
250+ if genesis .Config .IsQuorum {
251+ err = genesis .Config .CheckTransitionsData ()
252+ if err != nil {
253+ utils .Fatalf ("transitions data invalid: %v" , err )
254+ }
255+ } else {
256+ return fmt .Errorf ("update transitions only apply to quorum configuration" )
257+ }
258+
259+ // Update transitions and recommit to db
260+ for _ , name := range []string {"chaindata" , "lightchaindata" } {
261+ chaindb , err := stack .OpenDatabase (name , 0 , 0 , "" , false )
262+ if err != nil {
263+ utils .Fatalf ("Failed to open database: %v" , err )
264+ }
265+ stored := rawdb .ReadCanonicalHash (chaindb , 0 )
266+ storedcfg := rawdb .ReadChainConfig (chaindb , stored )
267+ if storedcfg == nil {
268+ return fmt .Errorf ("found genesis block without chain config" )
269+ }
270+ // Check that new transitions have changed before updating them
271+ if ! reflect .DeepEqual (storedcfg .Transitions , genesis .Config .Transitions ) {
272+ log .Info ("Change found in transitions, proceeding to update chain config" )
273+ storedcfg .Transitions = genesis .Config .Transitions
274+ rawdb .WriteChainConfig (chaindb , stored , storedcfg )
275+ } else {
276+ log .Info ("No change in transitions, no update required to chain config" )
277+ }
278+ }
279+ return nil
280+ }
281+
209282// initGenesis will initialise the given JSON format genesis file and writes it as
210283// the zero'd block (i.e. genesis) or will fail hard if it can't succeed.
211284func initGenesis (ctx * cli.Context ) error {
0 commit comments